From 4ca8d3417ca0d98f723cbf708cb37ca4f0eeec93 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 6 Dec 2023 01:01:06 +0200 Subject: SL-18107 Allow dropping inventory onto a profile for sharing --- indra/newview/llpanelprofile.cpp | 46 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'indra/newview/llpanelprofile.cpp') diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index c2c9139c19..24091644e3 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -46,6 +46,7 @@ #include "lltexteditor.h" #include "lltexturectrl.h" #include "lltoggleablemenu.h" +#include "lltooldraganddrop.h" #include "llgrouplist.h" #include "llurlaction.h" @@ -998,6 +999,51 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key) mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2)); } + +BOOL LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + // Try children first + if (LLPanelProfileTab::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) + && *accept != ACCEPT_NO) + { + return TRUE; + } + + // No point sharing with own profile + if (getSelfProfile()) + { + return FALSE; + } + + // Exclude fields that look like they are editable. + S32 child_x = 0; + S32 child_y = 0; + if (localPointToOtherView(x, y, &child_x, &child_y, mDescriptionEdit) + && mDescriptionEdit->pointInView(child_x, child_y)) + { + return FALSE; + } + + if (localPointToOtherView(x, y, &child_x, &child_y, mGroupList) + && mGroupList->pointInView(child_x, child_y)) + { + return FALSE; + } + + // Share + LLToolDragAndDrop::handleGiveDragAndDrop(getAvatarId(), + LLUUID::null, + drop, + cargo_type, + cargo_data, + accept); + return TRUE; +} + void LLPanelProfileSecondLife::updateData() { LLUUID avatar_id = getAvatarId(); -- cgit v1.2.3 From a5261a5fa8fad810ecb5c260d92c3e771822bf58 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Tue, 20 Feb 2024 23:46:23 +0100 Subject: Convert BOOL to bool in llui --- indra/newview/llpanelprofile.cpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'indra/newview/llpanelprofile.cpp') diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 00fa3853f7..be5783dd50 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -534,7 +534,7 @@ public: { if (params.size() < 2) return false; LLUUID avatar_id; - if (!avatar_id.set(params[0], FALSE)) + if (!avatar_id.set(params[0], false)) { return false; } @@ -661,7 +661,7 @@ class LLFloaterProfilePermissions public: LLFloaterProfilePermissions(LLView * owner, const LLUUID &avatar_id); ~LLFloaterProfilePermissions(); - BOOL postBuild() override; + bool postBuild() override; void onOpen(const LLSD& key) override; void draw() override; void changed(U32 mask) override; // LLFriendObserver @@ -713,7 +713,7 @@ LLFloaterProfilePermissions::~LLFloaterProfilePermissions() } } -BOOL LLFloaterProfilePermissions::postBuild() +bool LLFloaterProfilePermissions::postBuild() { mDescription = getChild("perm_description"); mOnlineStatus = getChild("online_check"); @@ -728,7 +728,7 @@ BOOL LLFloaterProfilePermissions::postBuild() mOkBtn->setCommitCallback([this](LLUICtrl*, void*) { onApplyRights(); }, nullptr); mCancelBtn->setCommitCallback([this](LLUICtrl*, void*) { onCancel(); }, nullptr); - return TRUE; + return true; } void LLFloaterProfilePermissions::onOpen(const LLSD& key) @@ -925,7 +925,7 @@ LLPanelProfileSecondLife::~LLPanelProfileSecondLife() } } -BOOL LLPanelProfileSecondLife::postBuild() +bool LLPanelProfileSecondLife::postBuild() { mGroupList = getChild("group_list"); mShowInSearchCombo = getChild("show_in_search"); @@ -957,7 +957,7 @@ BOOL LLPanelProfileSecondLife::postBuild() mCantEditObjectsIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); mSecondLifePic->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentProfileTexture(); }); - return TRUE; + return true; } void LLPanelProfileSecondLife::onOpen(const LLSD& key) @@ -1014,7 +1014,7 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key) } -BOOL LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, +bool LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, @@ -1024,13 +1024,13 @@ BOOL LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL d if (LLPanelProfileTab::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) && *accept != ACCEPT_NO) { - return TRUE; + return true; } // No point sharing with own profile if (getSelfProfile()) { - return FALSE; + return false; } // Exclude fields that look like they are editable. @@ -2124,13 +2124,13 @@ void LLPanelProfileWeb::onOpen(const LLSD& key) mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileWeb::onAvatarNameCache, this, _1, _2)); } -BOOL LLPanelProfileWeb::postBuild() +bool LLPanelProfileWeb::postBuild() { mWebBrowser = getChild("profile_html"); mWebBrowser->addObserver(this); mWebBrowser->setHomePageUrl("about:blank"); - return TRUE; + return true; } void LLPanelProfileWeb::resetData() @@ -2249,7 +2249,7 @@ LLPanelProfileFirstLife::~LLPanelProfileFirstLife() { } -BOOL LLPanelProfileFirstLife::postBuild() +bool LLPanelProfileFirstLife::postBuild() { mDescriptionEdit = getChild("fl_description_edit"); mPicture = getChild("real_world_pic"); @@ -2267,7 +2267,7 @@ BOOL LLPanelProfileFirstLife::postBuild() mDiscardChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardDescriptionChanges(); }, nullptr); mDescriptionEdit->setKeystrokeCallback([this](LLTextEditor* caller) { onSetDescriptionDirty(); }); - return TRUE; + return true; } void LLPanelProfileFirstLife::onOpen(const LLSD& key) @@ -2544,7 +2544,7 @@ void LLPanelProfileNotes::commitUnsavedChanges() } } -BOOL LLPanelProfileNotes::postBuild() +bool LLPanelProfileNotes::postBuild() { mNotesEditor = getChild("notes_edit"); mSaveChanges = getChild("notes_save_changes"); @@ -2554,7 +2554,7 @@ BOOL LLPanelProfileNotes::postBuild() mDiscardChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardNotesChanges(); }, nullptr); mNotesEditor->setKeystrokeCallback([this](LLTextEditor* caller) { onSetNotesDirty(); }); - return TRUE; + return true; } void LLPanelProfileNotes::onOpen(const LLSD& key) @@ -2639,9 +2639,9 @@ LLPanelProfile::~LLPanelProfile() { } -BOOL LLPanelProfile::postBuild() +bool LLPanelProfile::postBuild() { - return TRUE; + return true; } void LLPanelProfile::onTabChange() -- cgit v1.2.3 From 60d3dd98a44230c21803c1606552ee098ed9fa7c Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 21 Feb 2024 21:05:14 +0100 Subject: Convert remaining BOOL to bool --- indra/newview/llpanelprofile.cpp | 188 +++++++++++++++++++-------------------- 1 file changed, 94 insertions(+), 94 deletions(-) (limited to 'indra/newview/llpanelprofile.cpp') diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index be5783dd50..92a8a826ac 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -138,7 +138,7 @@ void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id) return; } - LLPanel *panel = floater_profile->findChild(PANEL_PROFILE_VIEW, TRUE); + LLPanel *panel = floater_profile->findChild(PANEL_PROFILE_VIEW, true); LLPanelProfile *panel_profile = dynamic_cast(panel); if (!panel_profile) { @@ -192,21 +192,21 @@ void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id) avatar_data->caption_text = result["caption"].asString(); } - panel = floater_profile->findChild(PANEL_SECONDLIFE, TRUE); + panel = floater_profile->findChild(PANEL_SECONDLIFE, true); LLPanelProfileSecondLife *panel_sl = dynamic_cast(panel); if (panel_sl) { panel_sl->processProfileProperties(avatar_data); } - panel = floater_profile->findChild(PANEL_WEB, TRUE); + panel = floater_profile->findChild(PANEL_WEB, true); LLPanelProfileWeb *panel_web = dynamic_cast(panel); if (panel_web) { panel_web->setLoaded(); } - panel = floater_profile->findChild(PANEL_FIRSTLIFE, TRUE); + panel = floater_profile->findChild(PANEL_FIRSTLIFE, true); LLPanelProfileFirstLife *panel_first = dynamic_cast(panel); if (panel_first) { @@ -226,7 +226,7 @@ void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id) avatar_picks.picks_list.emplace_back(pick_data["id"].asUUID(), pick_data["name"].asString()); } - panel = floater_profile->findChild(PANEL_PICKS, TRUE); + panel = floater_profile->findChild(PANEL_PICKS, true); LLPanelProfilePicks *panel_picks = dynamic_cast(panel); if (panel_picks) { @@ -267,7 +267,7 @@ void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id) avatar_notes.target_id = agent_id; avatar_notes.notes = result["notes"].asString(); - panel = floater_profile->findChild(PANEL_NOTES, TRUE); + panel = floater_profile->findChild(PANEL_NOTES, true); LLPanelProfileNotes *panel_notes = dynamic_cast(panel); if (panel_notes) { @@ -779,11 +779,11 @@ void LLFloaterProfilePermissions::fillRightsData() { S32 rights = relation->getRightsGrantedTo(); - BOOL see_online = LLRelationship::GRANT_ONLINE_STATUS & rights ? TRUE : FALSE; + bool see_online = LLRelationship::GRANT_ONLINE_STATUS & rights ? true : false; mOnlineStatus->setValue(see_online); mMapRights->setEnabled(see_online); - mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? TRUE : FALSE); - mEditObjectRights->setValue(LLRelationship::GRANT_MODIFY_OBJECTS & rights ? TRUE : FALSE); + mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? true : false); + mEditObjectRights->setValue(LLRelationship::GRANT_MODIFY_OBJECTS & rights ? true : false); } else { @@ -798,7 +798,7 @@ void LLFloaterProfilePermissions::rightsConfirmationCallback(const LLSD& notific S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option != 0) // canceled { - mEditObjectRights->setValue(mEditObjectRights->getValue().asBoolean() ? FALSE : TRUE); + mEditObjectRights->setValue(mEditObjectRights->getValue().asBoolean() ? false : true); } else { @@ -824,7 +824,7 @@ void LLFloaterProfilePermissions::onCommitSeeOnlineRights() if (relation) { S32 rights = relation->getRightsGrantedTo(); - mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? TRUE : FALSE); + mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? true : false); } else { @@ -834,7 +834,7 @@ void LLFloaterProfilePermissions::onCommitSeeOnlineRights() } else { - mMapRights->setValue(FALSE); + mMapRights->setValue(false); } mHasUnsavedPermChanges = true; } @@ -968,7 +968,7 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key) LLUUID avatar_id = getAvatarId(); - BOOL own_profile = getSelfProfile(); + bool own_profile = getSelfProfile(); mGroupList->setShowNone(!own_profile); @@ -1005,7 +1005,7 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key) if (!own_profile) { - mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(avatar_id) ? LLAvatarTracker::instance().isBuddyOnline(avatar_id) : TRUE); + mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(avatar_id) ? LLAvatarTracker::instance().isBuddyOnline(avatar_id) : true); updateOnlineStatus(); fillRightsData(); } @@ -1039,13 +1039,13 @@ bool LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, bool d if (localPointToOtherView(x, y, &child_x, &child_y, mDescriptionEdit) && mDescriptionEdit->pointInView(child_x, child_y)) { - return FALSE; + return false; } if (localPointToOtherView(x, y, &child_x, &child_y, mGroupList) && mGroupList->pointInView(child_x, child_y)) { - return FALSE; + return false; } // Share @@ -1055,7 +1055,7 @@ bool LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, bool d cargo_type, cargo_data, accept); - return TRUE; + return true; } void LLPanelProfileSecondLife::updateData() @@ -1116,9 +1116,9 @@ void LLPanelProfileSecondLife::resetData() mCanEditObjectsIcon->setEnabled(false); mCantEditObjectsIcon->setEnabled(false); - childSetVisible("partner_layout", FALSE); - childSetVisible("badge_layout", FALSE); - childSetVisible("partner_spacer_layout", TRUE); + childSetVisible("partner_layout", false); + childSetVisible("badge_layout", false); + childSetVisible("partner_spacer_layout", true); } void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avatar_data) @@ -1200,11 +1200,11 @@ void LLPanelProfileSecondLife::setProfileImageUploaded(const LLUUID &image_asset { imagep->setLoadedCallback(onImageLoaded, MAX_DISCARD_LEVEL, - FALSE, - FALSE, + false, + false, new LLHandle(getHandle()), NULL, - FALSE); + false); } LLFloater *floater = mFloaterProfileTextureHandle.get(); @@ -1287,17 +1287,17 @@ void LLPanelProfileSecondLife::fillCommonData(const LLAvatarData* avatar_data) { imagep->setLoadedCallback(onImageLoaded, MAX_DISCARD_LEVEL, - FALSE, - FALSE, + false, + false, new LLHandle(getHandle()), NULL, - FALSE); + false); } if (getSelfProfile()) { mAllowPublish = avatar_data->flags & AVATAR_ALLOW_PUBLISH; - mShowInSearchCombo->setValue((BOOL)mAllowPublish); + mShowInSearchCombo->setValue((bool)mAllowPublish); } } @@ -1306,7 +1306,7 @@ void LLPanelProfileSecondLife::fillPartnerData(const LLAvatarData* avatar_data) LLTextBox* partner_text_ctrl = getChild("partner_link"); if (avatar_data->partner_id.notNull()) { - childSetVisible("partner_layout", TRUE); + childSetVisible("partner_layout", true); LLStringUtil::format_map_t args; args["[LINK]"] = LLSLURL("agent", avatar_data->partner_id, "inspect").getSLURLString(); std::string partner_text = getString("partner_text", args); @@ -1314,7 +1314,7 @@ void LLPanelProfileSecondLife::fillPartnerData(const LLAvatarData* avatar_data) } else { - childSetVisible("partner_layout", FALSE); + childSetVisible("partner_layout", false); } } @@ -1336,48 +1336,48 @@ void LLPanelProfileSecondLife::fillAccountStatus(const LLAvatarData* avatar_data { getChild("badge_icon")->setValue("Profile_Badge_Linden"); getChild("badge_text")->setValue(getString("BadgeLinden")); - childSetVisible("badge_layout", TRUE); - childSetVisible("partner_spacer_layout", FALSE); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); } else if (avatar_data->born_on < sl_release) { getChild("badge_icon")->setValue("Profile_Badge_Beta"); getChild("badge_text")->setValue(getString("BadgeBeta")); - childSetVisible("badge_layout", TRUE); - childSetVisible("partner_spacer_layout", FALSE); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); } else if (customer_lower == "beta_lifetime") { getChild("badge_icon")->setValue("Profile_Badge_Beta_Lifetime"); getChild("badge_text")->setValue(getString("BadgeBetaLifetime")); - childSetVisible("badge_layout", TRUE); - childSetVisible("partner_spacer_layout", FALSE); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); } else if (customer_lower == "lifetime") { getChild("badge_icon")->setValue("Profile_Badge_Lifetime"); getChild("badge_text")->setValue(getString("BadgeLifetime")); - childSetVisible("badge_layout", TRUE); - childSetVisible("partner_spacer_layout", FALSE); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); } else if (customer_lower == "secondlifetime_premium") { getChild("badge_icon")->setValue("Profile_Badge_Premium_Lifetime"); getChild("badge_text")->setValue(getString("BadgePremiumLifetime")); - childSetVisible("badge_layout", TRUE); - childSetVisible("partner_spacer_layout", FALSE); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); } else if (customer_lower == "secondlifetime_premium_plus") { getChild("badge_icon")->setValue("Profile_Badge_Pplus_Lifetime"); getChild("badge_text")->setValue(getString("BadgePremiumPlusLifetime")); - childSetVisible("badge_layout", TRUE); - childSetVisible("partner_spacer_layout", FALSE); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); } else { - childSetVisible("badge_layout", FALSE); - childSetVisible("partner_spacer_layout", TRUE); + childSetVisible("badge_layout", false); + childSetVisible("partner_spacer_layout", true); } } @@ -1439,7 +1439,7 @@ void LLPanelProfileSecondLife::fillAgeData(const LLDate &born_on) getChild("user_age")->setValue(register_date); } -void LLPanelProfileSecondLife::onImageLoaded(BOOL success, LLViewerFetchedTexture *imagep) +void LLPanelProfileSecondLife::onImageLoaded(bool success, LLViewerFetchedTexture *imagep) { LLRect imageRect = mSecondLifePicLayout->getRect(); if (!success || imagep->getFullWidth() == imagep->getFullHeight()) @@ -1454,12 +1454,12 @@ void LLPanelProfileSecondLife::onImageLoaded(BOOL success, LLViewerFetchedTextur } //static -void LLPanelProfileSecondLife::onImageLoaded(BOOL success, +void LLPanelProfileSecondLife::onImageLoaded(bool success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, - BOOL final, + bool final, void* userdata) { if (!userdata) return; @@ -1499,7 +1499,7 @@ void LLPanelProfileSecondLife::onChange(EStatusType status, const std::string &c return; } - mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(getAvatarId()) ? LLAvatarTracker::instance().isBuddyOnline(getAvatarId()) : TRUE); + mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(getAvatarId()) ? LLAvatarTracker::instance().isBuddyOnline(getAvatarId()) : true); } void LLPanelProfileSecondLife::setAvatarId(const LLUUID& avatar_id) @@ -1552,8 +1552,8 @@ void LLPanelProfileSecondLife::setLoaded() if (getSelfProfile()) { - mShowInSearchCombo->setEnabled(TRUE); - mDescriptionEdit->setEnabled(TRUE); + mShowInSearchCombo->setEnabled(true); + mDescriptionEdit->setEnabled(true); } } @@ -1863,8 +1863,8 @@ void LLPanelProfileSecondLife::onAvatarNameCacheSetName(const LLUUID& agent_id, void LLPanelProfileSecondLife::setDescriptionText(const std::string &text) { - mSaveDescriptionChanges->setEnabled(FALSE); - mDiscardDescriptionChanges->setEnabled(FALSE); + mSaveDescriptionChanges->setEnabled(false); + mDiscardDescriptionChanges->setEnabled(false); mHasUnsavedDescriptionChanges = false; mDescriptionText = text; @@ -1873,8 +1873,8 @@ void LLPanelProfileSecondLife::setDescriptionText(const std::string &text) void LLPanelProfileSecondLife::onSetDescriptionDirty() { - mSaveDescriptionChanges->setEnabled(TRUE); - mDiscardDescriptionChanges->setEnabled(TRUE); + mSaveDescriptionChanges->setEnabled(true); + mDiscardDescriptionChanges->setEnabled(true); mHasUnsavedDescriptionChanges = true; } @@ -1914,8 +1914,8 @@ void LLPanelProfileSecondLife::onSaveDescriptionChanges() LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; } - mSaveDescriptionChanges->setEnabled(FALSE); - mDiscardDescriptionChanges->setEnabled(FALSE); + mSaveDescriptionChanges->setEnabled(false); + mDiscardDescriptionChanges->setEnabled(false); mHasUnsavedDescriptionChanges = false; } @@ -1935,15 +1935,15 @@ void LLPanelProfileSecondLife::onShowAgentPermissionsDialog() LLFloaterProfilePermissions * perms = new LLFloaterProfilePermissions(parent_floater, getAvatarId()); mFloaterPermissionsHandle = perms->getHandle(); perms->openFloater(); - perms->setVisibleAndFrontmost(TRUE); + perms->setVisibleAndFrontmost(true); parent_floater->addDependentFloater(mFloaterPermissionsHandle); } } else // already open { - floater->setMinimized(FALSE); - floater->setVisibleAndFrontmost(TRUE); + floater->setMinimized(false); + floater->setVisibleAndFrontmost(true); } } @@ -1971,7 +1971,7 @@ void LLPanelProfileSecondLife::onShowAgentProfileTexture() texture_view->resetAsset(); } texture_view->openFloater(); - texture_view->setVisibleAndFrontmost(TRUE); + texture_view->setVisibleAndFrontmost(true); parent_floater->addDependentFloater(mFloaterProfileTextureHandle); } @@ -1979,8 +1979,8 @@ void LLPanelProfileSecondLife::onShowAgentProfileTexture() else // already open { LLFloaterProfileTexture * texture_view = dynamic_cast(floater); - texture_view->setMinimized(FALSE); - texture_view->setVisibleAndFrontmost(TRUE); + texture_view->setMinimized(false); + texture_view->setVisibleAndFrontmost(true); if (mImageId.notNull()) { texture_view->loadAsset(mImageId); @@ -2009,12 +2009,12 @@ void LLPanelProfileSecondLife::onShowTexturePicker() mImageId, LLUUID::null, mImageId, - FALSE, - FALSE, + false, + false, "SELECT PHOTO", PERM_NONE, PERM_NONE, - FALSE, + false, NULL); mFloaterTexturePickerHandle = texture_floaterp->getHandle(); @@ -2026,20 +2026,20 @@ void LLPanelProfileSecondLife::onShowTexturePicker() onCommitProfileImage(asset_id); } }); - texture_floaterp->setLocalTextureEnabled(FALSE); - texture_floaterp->setBakeTextureEnabled(FALSE); + texture_floaterp->setLocalTextureEnabled(false); + texture_floaterp->setBakeTextureEnabled(false); texture_floaterp->setCanApply(false, true, false); parent_floater->addDependentFloater(mFloaterTexturePickerHandle); texture_floaterp->openFloater(); - texture_floaterp->setFocus(TRUE); + texture_floaterp->setFocus(true); } } else { - floaterp->setMinimized(FALSE); - floaterp->setVisibleAndFrontmost(TRUE); + floaterp->setMinimized(false); + floaterp->setVisibleAndFrontmost(true); } } @@ -2145,7 +2145,7 @@ void LLPanelProfileWeb::updateData() { setIsLoading(); - mWebBrowser->setVisible(TRUE); + mWebBrowser->setVisible(true); mPerformanceTimer.start(); mWebBrowser->navigateTo(mURLWebProfile, HTTP_CONTENT_TEXT_HTML); } @@ -2182,7 +2182,7 @@ void LLPanelProfileWeb::onCommitLoad(LLUICtrl* ctrl) LLSD::String valstr = ctrl->getValue().asString(); if (valstr.empty()) { - mWebBrowser->setVisible(TRUE); + mWebBrowser->setVisible(true); mPerformanceTimer.start(); mWebBrowser->navigateTo( mURLHome, HTTP_CONTENT_TEXT_HTML ); } @@ -2277,7 +2277,7 @@ void LLPanelProfileFirstLife::onOpen(const LLSD& key) if (!getSelfProfile()) { // Otherwise as the only focusable element it will be selected - mDescriptionEdit->setTabStop(FALSE); + mDescriptionEdit->setTabStop(false); } resetData(); @@ -2344,12 +2344,12 @@ void LLPanelProfileFirstLife::onChangePhoto() mImageId, LLUUID::null, mImageId, - FALSE, - FALSE, + false, + false, "SELECT PHOTO", PERM_NONE, PERM_NONE, - FALSE, + false, NULL); mFloaterTexturePickerHandle = texture_floaterp->getHandle(); @@ -2361,19 +2361,19 @@ void LLPanelProfileFirstLife::onChangePhoto() onCommitPhoto(asset_id); } }); - texture_floaterp->setLocalTextureEnabled(FALSE); + texture_floaterp->setLocalTextureEnabled(false); texture_floaterp->setCanApply(false, true, false); parent_floater->addDependentFloater(mFloaterTexturePickerHandle); texture_floaterp->openFloater(); - texture_floaterp->setFocus(TRUE); + texture_floaterp->setFocus(true); } } else { - floaterp->setMinimized(FALSE); - floaterp->setVisibleAndFrontmost(TRUE); + floaterp->setMinimized(false); + floaterp->setVisibleAndFrontmost(true); } } @@ -2423,8 +2423,8 @@ void LLPanelProfileFirstLife::onCommitPhoto(const LLUUID& id) void LLPanelProfileFirstLife::setDescriptionText(const std::string &text) { - mSaveChanges->setEnabled(FALSE); - mDiscardChanges->setEnabled(FALSE); + mSaveChanges->setEnabled(false); + mDiscardChanges->setEnabled(false); mHasUnsavedChanges = false; mCurrentDescription = text; @@ -2433,8 +2433,8 @@ void LLPanelProfileFirstLife::setDescriptionText(const std::string &text) void LLPanelProfileFirstLife::onSetDescriptionDirty() { - mSaveChanges->setEnabled(TRUE); - mDiscardChanges->setEnabled(TRUE); + mSaveChanges->setEnabled(true); + mDiscardChanges->setEnabled(true); mHasUnsavedChanges = true; } @@ -2452,8 +2452,8 @@ void LLPanelProfileFirstLife::onSaveDescriptionChanges() LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; } - mSaveChanges->setEnabled(FALSE); - mDiscardChanges->setEnabled(FALSE); + mSaveChanges->setEnabled(false); + mDiscardChanges->setEnabled(false); mHasUnsavedChanges = false; } @@ -2499,8 +2499,8 @@ void LLPanelProfileFirstLife::setLoaded() if (getSelfProfile()) { - mDescriptionEdit->setEnabled(TRUE); - mPicture->setEnabled(TRUE); + mDescriptionEdit->setEnabled(true); + mPicture->setEnabled(true); mRemovePhoto->setEnabled(mImageId.notNull()); } } @@ -2566,8 +2566,8 @@ void LLPanelProfileNotes::onOpen(const LLSD& key) void LLPanelProfileNotes::setNotesText(const std::string &text) { - mSaveChanges->setEnabled(FALSE); - mDiscardChanges->setEnabled(FALSE); + mSaveChanges->setEnabled(false); + mDiscardChanges->setEnabled(false); mHasUnsavedChanges = false; mCurrentNotes = text; @@ -2576,8 +2576,8 @@ void LLPanelProfileNotes::setNotesText(const std::string &text) void LLPanelProfileNotes::onSetNotesDirty() { - mSaveChanges->setEnabled(TRUE); - mDiscardChanges->setEnabled(TRUE); + mSaveChanges->setEnabled(true); + mDiscardChanges->setEnabled(true); mHasUnsavedChanges = true; } @@ -2595,8 +2595,8 @@ void LLPanelProfileNotes::onSaveNotesChanges() LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; } - mSaveChanges->setEnabled(FALSE); - mDiscardChanges->setEnabled(FALSE); + mSaveChanges->setEnabled(false); + mDiscardChanges->setEnabled(false); mHasUnsavedChanges = false; } @@ -2608,7 +2608,7 @@ void LLPanelProfileNotes::onDiscardNotesChanges() void LLPanelProfileNotes::processProperties(LLAvatarNotes* avatar_notes) { setNotesText(avatar_notes->notes); - mNotesEditor->setEnabled(TRUE); + mNotesEditor->setEnabled(true); setLoaded(); } -- cgit v1.2.3 From f9473e8afcb624cc1b101195bf15943ec372b56f Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Mon, 6 May 2024 16:52:34 +0200 Subject: secondlife/viewer#1333 BOOL to bool conversion leftovers: ternaries --- indra/newview/llpanelprofile.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/newview/llpanelprofile.cpp') diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 3a26fb086b..0fc2ad4d6d 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -779,11 +779,11 @@ void LLFloaterProfilePermissions::fillRightsData() { S32 rights = relation->getRightsGrantedTo(); - bool see_online = LLRelationship::GRANT_ONLINE_STATUS & rights ? true : false; + bool see_online = LLRelationship::GRANT_ONLINE_STATUS & rights; mOnlineStatus->setValue(see_online); mMapRights->setEnabled(see_online); - mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? true : false); - mEditObjectRights->setValue(LLRelationship::GRANT_MODIFY_OBJECTS & rights ? true : false); + mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights); + mEditObjectRights->setValue(LLRelationship::GRANT_MODIFY_OBJECTS & rights); } else { @@ -798,7 +798,7 @@ void LLFloaterProfilePermissions::rightsConfirmationCallback(const LLSD& notific S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option != 0) // canceled { - mEditObjectRights->setValue(mEditObjectRights->getValue().asBoolean() ? false : true); + mEditObjectRights->setValue(!mEditObjectRights->getValue().asBoolean()); } else { @@ -824,7 +824,7 @@ void LLFloaterProfilePermissions::onCommitSeeOnlineRights() if (relation) { S32 rights = relation->getRightsGrantedTo(); - mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights ? true : false); + mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights); } else { -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/newview/llpanelprofile.cpp | 4862 +++++++++++++++++++------------------- 1 file changed, 2431 insertions(+), 2431 deletions(-) (limited to 'indra/newview/llpanelprofile.cpp') diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index adceee80d3..579f0941c3 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -1,2431 +1,2431 @@ -/** -* @file llpanelprofile.cpp -* @brief Profile panel implementation -* -* $LicenseInfo:firstyear=2022&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2022, 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" - -// Common -#include "llavatarnamecache.h" -#include "llsdutil.h" -#include "llslurl.h" -#include "lldateutil.h" //ageFromDate - -// UI -#include "llavatariconctrl.h" -#include "llclipboard.h" -#include "llcheckboxctrl.h" -#include "llcombobox.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 "lltooldraganddrop.h" -#include "llgrouplist.h" -#include "llurlaction.h" - -// Image -#include "llimagej2c.h" - -// Newview -#include "llagent.h" //gAgent -#include "llagentpicksinfo.h" -#include "llavataractions.h" -#include "llavatarpropertiesprocessor.h" -#include "llcallingcard.h" -#include "llcommandhandler.h" -#include "llfloaterprofiletexture.h" -#include "llfloaterreg.h" -#include "llfloaterreporter.h" -#include "llfilepicker.h" -#include "llfirstuse.h" -#include "llgroupactions.h" -#include "lllogchat.h" -#include "llmutelist.h" -#include "llnotificationsutil.h" -#include "llpanelblockedlist.h" -#include "llpanelprofileclassifieds.h" -#include "llpanelprofilepicks.h" -#include "lltrans.h" -#include "llviewercontrol.h" -#include "llviewermenu.h" //is_agent_mappable -#include "llviewermenufile.h" -#include "llviewertexturelist.h" -#include "llvoiceclient.h" -#include "llweb.h" - - -static LLPanelInjector t_panel_profile_secondlife("panel_profile_secondlife"); -static LLPanelInjector t_panel_web("panel_profile_web"); -static LLPanelInjector t_panel_picks("panel_profile_picks"); -static LLPanelInjector t_panel_firstlife("panel_profile_firstlife"); -static LLPanelInjector t_panel_notes("panel_profile_notes"); -static LLPanelInjector 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_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"; -static const std::string PANEL_PROFILE_VIEW = "panel_profile_view"; - -static const std::string PROFILE_PROPERTIES_CAP = "AgentProfile"; -static const std::string PROFILE_IMAGE_UPLOAD_CAP = "UploadAgentProfileImage"; - - -////////////////////////////////////////////////////////////////////////// - -LLUUID post_profile_image(std::string cap_url, const LLSD &first_data, std::string path_to_image, LLHandle *handle) -{ - LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t - httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("post_profile_image_coro", httpPolicy)); - LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - LLCore::HttpHeaders::ptr_t httpHeaders; - - LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); - httpOpts->setFollowRedirects(true); - - LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, first_data, httpOpts, httpHeaders); - - LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; - LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - - if (!status) - { - // todo: notification? - LL_WARNS("AvatarProperties") << "Failed to get uploader cap " << status.toString() << LL_ENDL; - return LLUUID::null; - } - if (!result.has("uploader")) - { - // todo: notification? - LL_WARNS("AvatarProperties") << "Failed to get uploader cap, response contains no data." << LL_ENDL; - return LLUUID::null; - } - std::string uploader_cap = result["uploader"].asString(); - if (uploader_cap.empty()) - { - LL_WARNS("AvatarProperties") << "Failed to get uploader cap, cap invalid." << LL_ENDL; - return LLUUID::null; - } - - // Upload the image - LLCore::HttpRequest::ptr_t uploaderhttpRequest(new LLCore::HttpRequest); - LLCore::HttpHeaders::ptr_t uploaderhttpHeaders(new LLCore::HttpHeaders); - LLCore::HttpOptions::ptr_t uploaderhttpOpts(new LLCore::HttpOptions); - S64 length; - - { - llifstream instream(path_to_image.c_str(), std::iostream::binary | std::iostream::ate); - if (!instream.is_open()) - { - LL_WARNS("AvatarProperties") << "Failed to open file " << path_to_image << LL_ENDL; - return LLUUID::null; - } - length = instream.tellg(); - } - - uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, "application/jp2"); // optional - uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_LENGTH, llformat("%d", length)); // required! - uploaderhttpOpts->setFollowRedirects(true); - - result = httpAdapter->postFileAndSuspend(uploaderhttpRequest, uploader_cap, path_to_image, uploaderhttpOpts, uploaderhttpHeaders); - - httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; - status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - - LL_DEBUGS("AvatarProperties") << result << LL_ENDL; - - if (!status) - { - LL_WARNS("AvatarProperties") << "Failed to upload image " << status.toString() << LL_ENDL; - return LLUUID::null; - } - - if (result["state"].asString() != "complete") - { - if (result.has("message")) - { - LL_WARNS("AvatarProperties") << "Failed to upload image, state " << result["state"] << " message: " << result["message"] << LL_ENDL; - } - else - { - LL_WARNS("AvatarProperties") << "Failed to upload image " << result << LL_ENDL; - } - return LLUUID::null; - } - - return result["new_asset"].asUUID(); -} - -enum EProfileImageType -{ - PROFILE_IMAGE_SL, - PROFILE_IMAGE_FL, -}; - -void post_profile_image_coro(std::string cap_url, EProfileImageType type, std::string path_to_image, LLHandle *handle) -{ - LLSD data; - switch (type) - { - case PROFILE_IMAGE_SL: - data["profile-image-asset"] = "sl_image_id"; - break; - case PROFILE_IMAGE_FL: - data["profile-image-asset"] = "fl_image_id"; - break; - } - - LLUUID result = post_profile_image(cap_url, data, path_to_image, handle); - - // reset loading indicator - if (!handle->isDead()) - { - switch (type) - { - case PROFILE_IMAGE_SL: - { - LLPanelProfileSecondLife* panel = static_cast(handle->get()); - if (result.notNull()) - { - panel->setProfileImageUploaded(result); - } - else - { - // failure, just stop progress indicator - panel->setProfileImageUploading(false); - } - break; - } - case PROFILE_IMAGE_FL: - { - LLPanelProfileFirstLife* panel = static_cast(handle->get()); - if (result.notNull()) - { - panel->setProfileImageUploaded(result); - } - else - { - // failure, just stop progress indicator - panel->setProfileImageUploading(false); - } - break; - } - } - } - - if (type == PROFILE_IMAGE_SL && result.notNull()) - { - LLAvatarIconIDCache::getInstance()->add(gAgentID, result); - // Should trigger callbacks in icon controls - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(gAgentID); - } - - // Cleanup - LLFile::remove(path_to_image); - delete handle; -} - -////////////////////////////////////////////////////////////////////////// -// 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, - const std::string& grid, - 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; - - -////////////////////////////////////////////////////////////////////////// -// LLAgentHandler - -class LLAgentHandler : public LLCommandHandler -{ -public: - // requires trusted browser to trigger - LLAgentHandler() : LLCommandHandler("agent", UNTRUSTED_THROTTLE) { } - - virtual bool canHandleUntrusted( - const LLSD& params, - const LLSD& query_map, - LLMediaCtrl* web, - const std::string& nav_type) - { - if (params.size() < 2) - { - return true; // don't block, will fail later - } - - if (nav_type == NAV_TYPE_CLICKED - || nav_type == NAV_TYPE_EXTERNAL) - { - return true; - } - - const std::string verb = params[1].asString(); - if (verb == "about" || verb == "inspect" || verb == "reportAbuse") - { - return true; - } - return false; - } - - bool handle(const LLSD& params, - const LLSD& query_map, - const std::string& grid, - LLMediaCtrl* web) - { - if (params.size() < 2) return false; - LLUUID avatar_id; - if (!avatar_id.set(params[0], false)) - { - return false; - } - - const std::string verb = params[1].asString(); - if (verb == "about") - { - LLAvatarActions::showProfile(avatar_id); - return true; - } - - if (verb == "inspect") - { - LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", avatar_id)); - return true; - } - - if (verb == "im") - { - LLAvatarActions::startIM(avatar_id); - return true; - } - - if (verb == "pay") - { - if (!LLUI::getInstance()->mSettingGroups["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; - } - - if (verb == "block") - { - if (params.size() > 2) - { - 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; - } - - // reportAbuse is here due to convoluted avatar handling - // in LLScrollListCtrl and LLTextBase - if (verb == "reportAbuse" && web == NULL) - { - LLAvatarName av_name; - if (LLAvatarNameCache::get(avatar_id, &av_name)) - { - LLFloaterReporter::showFromAvatar(avatar_id, av_name.getCompleteName()); - } - else - { - LLFloaterReporter::showFromAvatar(avatar_id, "not avaliable"); - } - return true; - } - return false; - } -}; -LLAgentHandler gAgentHandler; - - -///---------------------------------------------------------------------------- -/// LLFloaterProfilePermissions -///---------------------------------------------------------------------------- - -class LLFloaterProfilePermissions - : public LLFloater - , public LLFriendObserver -{ -public: - LLFloaterProfilePermissions(LLView * owner, const LLUUID &avatar_id); - ~LLFloaterProfilePermissions(); - bool postBuild() override; - void onOpen(const LLSD& key) override; - void draw() override; - void changed(U32 mask) override; // LLFriendObserver - - void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); - bool hasUnsavedChanges() { return mHasUnsavedPermChanges; } - - void onApplyRights(); - -private: - void fillRightsData(); - void rightsConfirmationCallback(const LLSD& notification, const LLSD& response); - void confirmModifyRights(bool grant); - void onCommitSeeOnlineRights(); - void onCommitEditRights(); - void onCancel(); - - LLTextBase* mDescription; - LLCheckBoxCtrl* mOnlineStatus; - LLCheckBoxCtrl* mMapRights; - LLCheckBoxCtrl* mEditObjectRights; - LLButton* mOkBtn; - LLButton* mCancelBtn; - - LLUUID mAvatarID; - F32 mContextConeOpacity; - bool mHasUnsavedPermChanges; - LLHandle mOwnerHandle; - - boost::signals2::connection mAvatarNameCacheConnection; -}; - -LLFloaterProfilePermissions::LLFloaterProfilePermissions(LLView * owner, const LLUUID &avatar_id) - : LLFloater(LLSD()) - , mAvatarID(avatar_id) - , mContextConeOpacity(0.0f) - , mHasUnsavedPermChanges(false) - , mOwnerHandle(owner->getHandle()) -{ - buildFromFile("floater_profile_permissions.xml"); -} - -LLFloaterProfilePermissions::~LLFloaterProfilePermissions() -{ - mAvatarNameCacheConnection.disconnect(); - if (mAvatarID.notNull()) - { - LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this); - } -} - -bool LLFloaterProfilePermissions::postBuild() -{ - mDescription = getChild("perm_description"); - mOnlineStatus = getChild("online_check"); - mMapRights = getChild("map_check"); - mEditObjectRights = getChild("objects_check"); - mOkBtn = getChild("perms_btn_ok"); - mCancelBtn = getChild("perms_btn_cancel"); - - mOnlineStatus->setCommitCallback([this](LLUICtrl*, void*) { onCommitSeeOnlineRights(); }, nullptr); - mMapRights->setCommitCallback([this](LLUICtrl*, void*) { mHasUnsavedPermChanges = true; }, nullptr); - mEditObjectRights->setCommitCallback([this](LLUICtrl*, void*) { onCommitEditRights(); }, nullptr); - mOkBtn->setCommitCallback([this](LLUICtrl*, void*) { onApplyRights(); }, nullptr); - mCancelBtn->setCommitCallback([this](LLUICtrl*, void*) { onCancel(); }, nullptr); - - return true; -} - -void LLFloaterProfilePermissions::onOpen(const LLSD& key) -{ - if (LLAvatarActions::isFriend(mAvatarID)) - { - LLAvatarTracker::instance().addParticularFriendObserver(mAvatarID, this); - fillRightsData(); - } - - mCancelBtn->setFocus(true); - - mAvatarNameCacheConnection = LLAvatarNameCache::get(mAvatarID, boost::bind(&LLFloaterProfilePermissions::onAvatarNameCache, this, _1, _2)); -} - -void LLFloaterProfilePermissions::draw() -{ - // drawFrustum - LLView *owner = mOwnerHandle.get(); - static LLCachedControl max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f); - drawConeToOwner(mContextConeOpacity, max_opacity, owner); - LLFloater::draw(); -} - -void LLFloaterProfilePermissions::changed(U32 mask) -{ - if (mask != LLFriendObserver::ONLINE) - { - fillRightsData(); - } -} - -void LLFloaterProfilePermissions::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) -{ - mAvatarNameCacheConnection.disconnect(); - - LLStringUtil::format_map_t args; - args["[AGENT_NAME]"] = av_name.getDisplayName(); - std::string descritpion = getString("description_string", args); - mDescription->setValue(descritpion); -} - -void LLFloaterProfilePermissions::fillRightsData() -{ - const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); - // If true - we are viewing friend's profile, enable check boxes and set values. - if (relation) - { - S32 rights = relation->getRightsGrantedTo(); - - bool see_online = LLRelationship::GRANT_ONLINE_STATUS & rights; - mOnlineStatus->setValue(see_online); - mMapRights->setEnabled(see_online); - mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights); - mEditObjectRights->setValue(LLRelationship::GRANT_MODIFY_OBJECTS & rights); - } - else - { - closeFloater(); - LL_INFOS("ProfilePermissions") << "Floater closing since agent is no longer a friend" << LL_ENDL; - } -} - -void LLFloaterProfilePermissions::rightsConfirmationCallback(const LLSD& notification, - const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) // canceled - { - mEditObjectRights->setValue(!mEditObjectRights->getValue().asBoolean()); - } - else - { - mHasUnsavedPermChanges = true; - } -} - -void LLFloaterProfilePermissions::confirmModifyRights(bool grant) -{ - LLSD args; - args["NAME"] = LLSLURL("agent", mAvatarID, "completename").getSLURLString(); - LLNotificationsUtil::add(grant ? "GrantModifyRights" : "RevokeModifyRights", args, LLSD(), - boost::bind(&LLFloaterProfilePermissions::rightsConfirmationCallback, this, _1, _2)); -} - -void LLFloaterProfilePermissions::onCommitSeeOnlineRights() -{ - bool see_online = mOnlineStatus->getValue().asBoolean(); - mMapRights->setEnabled(see_online); - if (see_online) - { - const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); - if (relation) - { - S32 rights = relation->getRightsGrantedTo(); - mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights); - } - else - { - closeFloater(); - LL_INFOS("ProfilePermissions") << "Floater closing since agent is no longer a friend" << LL_ENDL; - } - } - else - { - mMapRights->setValue(false); - } - mHasUnsavedPermChanges = true; -} - -void LLFloaterProfilePermissions::onCommitEditRights() -{ - const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); - - if (!buddy_relationship) - { - LL_WARNS("ProfilePermissions") << "Trying to modify rights for non-friend avatar. Closing floater." << LL_ENDL; - closeFloater(); - return; - } - - bool allow_modify_objects = mEditObjectRights->getValue().asBoolean(); - - // if modify objects checkbox clicked - if (buddy_relationship->isRightGrantedTo( - LLRelationship::GRANT_MODIFY_OBJECTS) != allow_modify_objects) - { - confirmModifyRights(allow_modify_objects); - } -} - -void LLFloaterProfilePermissions::onApplyRights() -{ - const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); - - if (!buddy_relationship) - { - LL_WARNS("ProfilePermissions") << "Trying to modify rights for non-friend avatar. Skipped." << LL_ENDL; - return; - } - - S32 rights = 0; - - if (mOnlineStatus->getValue().asBoolean()) - { - rights |= LLRelationship::GRANT_ONLINE_STATUS; - } - if (mMapRights->getValue().asBoolean()) - { - rights |= LLRelationship::GRANT_MAP_LOCATION; - } - if (mEditObjectRights->getValue().asBoolean()) - { - rights |= LLRelationship::GRANT_MODIFY_OBJECTS; - } - - LLAvatarPropertiesProcessor::getInstance()->sendFriendRights(mAvatarID, rights); - - closeFloater(); -} - -void LLFloaterProfilePermissions::onCancel() -{ - closeFloater(); -} - -////////////////////////////////////////////////////////////////////////// -// LLPanelProfileSecondLife - -LLPanelProfileSecondLife::LLPanelProfileSecondLife() - : LLPanelProfilePropertiesProcessorTab() - , mAvatarNameCacheConnection() - , mHasUnsavedDescriptionChanges(false) - , mWaitingForImageUpload(false) - , mAllowPublish(false) - , mHideAge(false) -{ -} - -LLPanelProfileSecondLife::~LLPanelProfileSecondLife() -{ - if (getAvatarId().notNull()) - { - LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); - } - - if (LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this); - } - - if (mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection.disconnect(); - } -} - -bool LLPanelProfileSecondLife::postBuild() -{ - mGroupList = getChild("group_list"); - mShowInSearchCombo = getChild("show_in_search"); - mHideAgeCombo = getChild("hide_age"); - mSecondLifePic = getChild("2nd_life_pic"); - mSecondLifePicLayout = getChild("image_panel"); - mDescriptionEdit = getChild("sl_description_edit"); - mAgentActionMenuButton = getChild("agent_actions_menu"); - mSaveDescriptionChanges = getChild("save_description_changes"); - mDiscardDescriptionChanges = getChild("discard_description_changes"); - mCanSeeOnlineIcon = getChild("can_see_online"); - mCantSeeOnlineIcon = getChild("cant_see_online"); - mCanSeeOnMapIcon = getChild("can_see_on_map"); - mCantSeeOnMapIcon = getChild("cant_see_on_map"); - mCanEditObjectsIcon = getChild("can_edit_objects"); - mCantEditObjectsIcon = getChild("cant_edit_objects"); - - mShowInSearchCombo->setCommitCallback([this](LLUICtrl*, void*) { onShowInSearchCallback(); }, nullptr); - mHideAgeCombo->setCommitCallback([this](LLUICtrl*, void*) { onHideAgeCallback(); }, nullptr); - mGroupList->setDoubleClickCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { LLPanelProfileSecondLife::openGroupProfile(); }); - mGroupList->setReturnCallback([this](LLUICtrl*, const LLSD&) { LLPanelProfileSecondLife::openGroupProfile(); }); - mSaveDescriptionChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveDescriptionChanges(); }, nullptr); - mDiscardDescriptionChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardDescriptionChanges(); }, nullptr); - mDescriptionEdit->setKeystrokeCallback([this](LLTextEditor* caller) { onSetDescriptionDirty(); }); - - mCanSeeOnlineIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); - mCantSeeOnlineIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); - mCanSeeOnMapIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); - mCantSeeOnMapIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); - mCanEditObjectsIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); - mCantEditObjectsIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); - mSecondLifePic->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentProfileTexture(); }); - - return true; -} - -void LLPanelProfileSecondLife::onOpen(const LLSD& key) -{ - LLPanelProfileTab::onOpen(key); - - resetData(); - - LLUUID avatar_id = getAvatarId(); - - bool own_profile = getSelfProfile(); - - mGroupList->setShowNone(!own_profile); - - childSetVisible("notes_panel", !own_profile); - childSetVisible("settings_panel", own_profile); - childSetVisible("about_buttons_panel", own_profile); - - if (own_profile) - { - // Group list control cannot toggle ForAgent loading - // Less than ideal, but viewing own profile via search is edge case - mGroupList->enableForAgent(false); - } - - // Init menu, menu needs to be created in scope of a registar to work correctly. - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar commit; - commit.add("Profile.Commit", [this](LLUICtrl*, const LLSD& userdata) { onCommitMenu(userdata); }); - - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable; - enable.add("Profile.EnableItem", [this](LLUICtrl*, const LLSD& userdata) { return onEnableMenu(userdata); }); - enable.add("Profile.CheckItem", [this](LLUICtrl*, const LLSD& userdata) { return onCheckMenu(userdata); }); - - if (own_profile) - { - mAgentActionMenuButton->setMenu("menu_profile_self.xml", LLMenuButton::MP_BOTTOM_RIGHT); - } - else - { - // Todo: use PeopleContextMenu instead? - mAgentActionMenuButton->setMenu("menu_profile_other.xml", LLMenuButton::MP_BOTTOM_RIGHT); - } - - mDescriptionEdit->setParseHTML(!own_profile); - - if (!own_profile) - { - mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(avatar_id) ? LLAvatarTracker::instance().isBuddyOnline(avatar_id) : true); - updateOnlineStatus(); - fillRightsData(); - } - - mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2)); -} - - -bool LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - // Try children first - if (LLPanelProfileTab::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) - && *accept != ACCEPT_NO) - { - return true; - } - - // No point sharing with own profile - if (getSelfProfile()) - { - return false; - } - - // Exclude fields that look like they are editable. - S32 child_x = 0; - S32 child_y = 0; - if (localPointToOtherView(x, y, &child_x, &child_y, mDescriptionEdit) - && mDescriptionEdit->pointInView(child_x, child_y)) - { - return false; - } - - if (localPointToOtherView(x, y, &child_x, &child_y, mGroupList) - && mGroupList->pointInView(child_x, child_y)) - { - return false; - } - - // Share - LLToolDragAndDrop::handleGiveDragAndDrop(getAvatarId(), - LLUUID::null, - drop, - cargo_type, - cargo_data, - accept); - return true; -} - -void LLPanelProfileSecondLife::refreshName() -{ - if (!mAvatarNameCacheConnection.connected()) - { - mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2)); - } -} - -void LLPanelProfileSecondLife::resetData() -{ - resetLoading(); - - // Set default image and 1:1 dimensions for it - mSecondLifePic->setValue("Generic_Person_Large"); - - LLRect imageRect = mSecondLifePicLayout->getRect(); - mSecondLifePicLayout->reshape(imageRect.getWidth(), imageRect.getWidth()); - - setDescriptionText(LLStringUtil::null); - mGroups.clear(); - mGroupList->setGroups(mGroups); - - bool own_profile = getSelfProfile(); - mCanSeeOnlineIcon->setVisible(false); - mCantSeeOnlineIcon->setVisible(!own_profile); - mCanSeeOnMapIcon->setVisible(false); - mCantSeeOnMapIcon->setVisible(!own_profile); - mCanEditObjectsIcon->setVisible(false); - mCantEditObjectsIcon->setVisible(!own_profile); - - mCanSeeOnlineIcon->setEnabled(false); - mCantSeeOnlineIcon->setEnabled(false); - mCanSeeOnMapIcon->setEnabled(false); - mCantSeeOnMapIcon->setEnabled(false); - mCanEditObjectsIcon->setEnabled(false); - mCantEditObjectsIcon->setEnabled(false); - - childSetVisible("partner_layout", false); - childSetVisible("badge_layout", false); - childSetVisible("partner_spacer_layout", true); -} - -void LLPanelProfileSecondLife::processProperties(void* data, EAvatarProcessorType type) -{ - if (APT_PROPERTIES == type) - { - LLAvatarData* avatar_data = static_cast(data); - if (avatar_data && getAvatarId() == avatar_data->avatar_id) - { - processProfileProperties(avatar_data); - } - } -} - -void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avatar_data) -{ - const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); - if ((relationship != NULL || gAgent.isGodlike()) && !getSelfProfile()) - { - // Relies onto friend observer to get information about online status updates. - // Once SL-17506 gets implemented, condition might need to become: - // (gAgent.isGodlike() || isRightGrantedFrom || flags & AVATAR_ONLINE) - processOnlineStatus(relationship != NULL, - gAgent.isGodlike() || relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS), - (avatar_data->flags & AVATAR_ONLINE)); - } - - fillCommonData(avatar_data); - - fillPartnerData(avatar_data); - - fillAccountStatus(avatar_data); - - LLAvatarData::group_list_t::const_iterator it = avatar_data->group_list.begin(); - const LLAvatarData::group_list_t::const_iterator it_end = avatar_data->group_list.end(); - - for (; it_end != it; ++it) - { - LLAvatarData::LLGroupData group_data = *it; - mGroups[group_data.group_name] = group_data.group_id; - } - - mGroupList->setGroups(mGroups); - - setLoaded(); -} - -void LLPanelProfileSecondLife::openGroupProfile() -{ - LLUUID group_id = mGroupList->getSelectedUUID(); - LLGroupActions::show(group_id); -} - -void LLPanelProfileSecondLife::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) -{ - mAvatarNameCacheConnection.disconnect(); - getChild("display_name")->setValue(av_name.getDisplayName()); - getChild("user_name")->setValue(av_name.getAccountName()); -} - -void LLPanelProfileSecondLife::setProfileImageUploading(bool loading) -{ - LLLoadingIndicator* indicator = getChild("image_upload_indicator"); - indicator->setVisible(loading); - if (loading) - { - indicator->start(); - } - else - { - indicator->stop(); - } - mWaitingForImageUpload = loading; -} - -void LLPanelProfileSecondLife::setProfileImageUploaded(const LLUUID &image_asset_id) -{ - mSecondLifePic->setValue(image_asset_id); - - LLFloater *floater = mFloaterProfileTextureHandle.get(); - if (floater) - { - LLFloaterProfileTexture * texture_view = dynamic_cast(floater); - texture_view->loadAsset(mSecondLifePic->getImageAssetId()); - } - - setProfileImageUploading(false); -} - -bool LLPanelProfileSecondLife::hasUnsavedChanges() -{ - LLFloater *floater = mFloaterPermissionsHandle.get(); - if (floater) - { - LLFloaterProfilePermissions* perm = dynamic_cast(floater); - if (perm && perm->hasUnsavedChanges()) - { - return true; - } - } - // if floater - return mHasUnsavedDescriptionChanges; -} - -void LLPanelProfileSecondLife::commitUnsavedChanges() -{ - LLFloater *floater = mFloaterPermissionsHandle.get(); - if (floater) - { - LLFloaterProfilePermissions* perm = dynamic_cast(floater); - if (perm && perm->hasUnsavedChanges()) - { - perm->onApplyRights(); - } - } - if (mHasUnsavedDescriptionChanges) - { - onSaveDescriptionChanges(); - } -} - -void LLPanelProfileSecondLife::fillCommonData(const LLAvatarData* avatar_data) -{ - // Refresh avatar id in cache with new info to prevent re-requests - // and to make sure icons in text will be up to date - LLAvatarIconIDCache::getInstance()->add(avatar_data->avatar_id, avatar_data->image_id); - - fillAgeData(avatar_data); - - setDescriptionText(avatar_data->about_text); - - mSecondLifePic->setValue(avatar_data->image_id); - - if (getSelfProfile()) - { - mAllowPublish = avatar_data->flags & AVATAR_ALLOW_PUBLISH; - mShowInSearchCombo->setValue(mAllowPublish); - } -} - -void LLPanelProfileSecondLife::fillPartnerData(const LLAvatarData* avatar_data) -{ - LLTextBox* partner_text_ctrl = getChild("partner_link"); - if (avatar_data->partner_id.notNull()) - { - childSetVisible("partner_layout", true); - LLStringUtil::format_map_t args; - args["[LINK]"] = LLSLURL("agent", avatar_data->partner_id, "inspect").getSLURLString(); - std::string partner_text = getString("partner_text", args); - partner_text_ctrl->setText(partner_text); - } - else - { - childSetVisible("partner_layout", false); - } -} - -void LLPanelProfileSecondLife::fillAccountStatus(const LLAvatarData* avatar_data) -{ - LLStringUtil::format_map_t args; - args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(avatar_data); - args["[PAYMENTINFO]"] = LLAvatarPropertiesProcessor::paymentInfo(avatar_data); - - std::string caption_text = getString("CaptionTextAcctInfo", args); - getChild("account_info")->setValue(caption_text); - - const S32 LINDEN_EMPLOYEE_INDEX = 3; - LLDate sl_release; - sl_release.fromYMDHMS(2003, 6, 23, 0, 0, 0); - std::string customer_lower = avatar_data->customer_type; - LLStringUtil::toLower(customer_lower); - if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX) - { - getChild("badge_icon")->setValue("Profile_Badge_Linden"); - getChild("badge_text")->setValue(getString("BadgeLinden")); - childSetVisible("badge_layout", true); - childSetVisible("partner_spacer_layout", false); - } - else if (avatar_data->born_on < sl_release) - { - getChild("badge_icon")->setValue("Profile_Badge_Beta"); - getChild("badge_text")->setValue(getString("BadgeBeta")); - childSetVisible("badge_layout", true); - childSetVisible("partner_spacer_layout", false); - } - else if (customer_lower == "beta_lifetime") - { - getChild("badge_icon")->setValue("Profile_Badge_Beta_Lifetime"); - getChild("badge_text")->setValue(getString("BadgeBetaLifetime")); - childSetVisible("badge_layout", true); - childSetVisible("partner_spacer_layout", false); - } - else if (customer_lower == "lifetime") - { - getChild("badge_icon")->setValue("Profile_Badge_Lifetime"); - getChild("badge_text")->setValue(getString("BadgeLifetime")); - childSetVisible("badge_layout", true); - childSetVisible("partner_spacer_layout", false); - } - else if (customer_lower == "secondlifetime_premium") - { - getChild("badge_icon")->setValue("Profile_Badge_Premium_Lifetime"); - getChild("badge_text")->setValue(getString("BadgePremiumLifetime")); - childSetVisible("badge_layout", true); - childSetVisible("partner_spacer_layout", false); - } - else if (customer_lower == "secondlifetime_premium_plus") - { - getChild("badge_icon")->setValue("Profile_Badge_Pplus_Lifetime"); - getChild("badge_text")->setValue(getString("BadgePremiumPlusLifetime")); - childSetVisible("badge_layout", true); - childSetVisible("partner_spacer_layout", false); - } - else - { - childSetVisible("badge_layout", false); - childSetVisible("partner_spacer_layout", true); - } -} - -void LLPanelProfileSecondLife::fillRightsData() -{ - if (getSelfProfile()) - { - return; - } - - 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(); - bool can_see_online = LLRelationship::GRANT_ONLINE_STATUS & rights; - bool can_see_on_map = LLRelationship::GRANT_MAP_LOCATION & rights; - bool can_edit_objects = LLRelationship::GRANT_MODIFY_OBJECTS & rights; - - mCanSeeOnlineIcon->setVisible(can_see_online); - mCantSeeOnlineIcon->setVisible(!can_see_online); - mCanSeeOnMapIcon->setVisible(can_see_on_map); - mCantSeeOnMapIcon->setVisible(!can_see_on_map); - mCanEditObjectsIcon->setVisible(can_edit_objects); - mCantEditObjectsIcon->setVisible(!can_edit_objects); - - mCanSeeOnlineIcon->setEnabled(true); - mCantSeeOnlineIcon->setEnabled(true); - mCanSeeOnMapIcon->setEnabled(true); - mCantSeeOnMapIcon->setEnabled(true); - mCanEditObjectsIcon->setEnabled(true); - mCantEditObjectsIcon->setEnabled(true); - } - else - { - mCanSeeOnlineIcon->setVisible(false); - mCantSeeOnlineIcon->setVisible(false); - mCanSeeOnMapIcon->setVisible(false); - mCantSeeOnMapIcon->setVisible(false); - mCanEditObjectsIcon->setVisible(false); - mCantEditObjectsIcon->setVisible(false); - } -} - -void LLPanelProfileSecondLife::fillAgeData(const LLAvatarData* avatar_data) -{ - // Date from server comes already converted to stl timezone, - // so display it as an UTC + 0 - bool hide_age = avatar_data->hide_age && !getSelfProfile(); - std::string name_and_date = getString(hide_age ? "date_format_short" : "date_format_full"); - LLSD args_name; - args_name["datetime"] = (S32)avatar_data->born_on.secondsSinceEpoch(); - LLStringUtil::format(name_and_date, args_name); - getChild("sl_birth_date")->setValue(name_and_date); - - LLUICtrl* userAgeCtrl = getChild("user_age"); - if (hide_age) - { - userAgeCtrl->setVisible(false); - } - else - { - std::string register_date = getString("age_format"); - LLSD args_age; - args_age["[AGE]"] = LLDateUtil::ageFromDate(avatar_data->born_on, LLDate::now()); - LLStringUtil::format(register_date, args_age); - userAgeCtrl->setValue(register_date); - } - - bool showHideAgeCombo = false; - if (getSelfProfile()) - { - if (LLAvatarPropertiesProcessor::getInstance()->isHideAgeSupportedByServer()) - { - F64 birth = avatar_data->born_on.secondsSinceEpoch(); - F64 now = LLDate::now().secondsSinceEpoch(); - if (now - birth > 365 * 24 * 60 * 60) - { - mHideAge = avatar_data->hide_age; - mHideAgeCombo->setValue(mHideAge); - showHideAgeCombo = true; - } - } - } - mHideAgeCombo->setVisible(showHideAgeCombo); -} - -void LLPanelProfileSecondLife::onImageLoaded(bool success, LLViewerFetchedTexture *imagep) -{ - LLRect imageRect = mSecondLifePicLayout->getRect(); - if (!success || imagep->getFullWidth() == imagep->getFullHeight()) - { - mSecondLifePicLayout->reshape(imageRect.getWidth(), imageRect.getWidth()); - } - else - { - // assume 3:4, for sake of firestorm - mSecondLifePicLayout->reshape(imageRect.getWidth(), imageRect.getWidth() * 3 / 4); - } -} - -// virtual, called by LLAvatarTracker -void LLPanelProfileSecondLife::changed(U32 mask) -{ - updateOnlineStatus(); - if (mask != LLFriendObserver::ONLINE) - { - fillRightsData(); - } -} - -// virtual, called by LLVoiceClient -void LLPanelProfileSecondLife::onChange(EStatusType status, const std::string &channelURI, bool proximal) -{ - 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); - } - - LLPanelProfilePropertiesProcessorTab::setAvatarId(avatar_id); - - if (LLAvatarActions::isFriend(getAvatarId())) - { - LLAvatarTracker::instance().addParticularFriendObserver(getAvatarId(), this); - } - } -} - -// method was disabled according to EXT-2022. Re-enabled & improved according to EXT-3880 -void LLPanelProfileSecondLife::updateOnlineStatus() -{ - const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); - if (relationship != NULL) - { - // For friend let check if he allowed me to see his status - bool online = relationship->isOnline(); - bool perm_granted = relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS); - processOnlineStatus(true, perm_granted, online); - } - else - { - childSetVisible("friend_layout", false); - childSetVisible("online_layout", false); - childSetVisible("offline_layout", false); - } -} - -void LLPanelProfileSecondLife::processOnlineStatus(bool is_friend, bool show_online, bool online) -{ - childSetVisible("friend_layout", is_friend); - childSetVisible("online_layout", online && show_online); - childSetVisible("offline_layout", !online && show_online); -} - -void LLPanelProfileSecondLife::setLoaded() -{ - LLPanelProfileTab::setLoaded(); - - if (getSelfProfile()) - { - mShowInSearchCombo->setEnabled(true); - if (mHideAgeCombo->getVisible()) - { - mHideAgeCombo->setEnabled(true); - } - mDescriptionEdit->setEnabled(true); - } -} - - -class LLProfileImagePicker : public LLFilePickerThread -{ -public: - LLProfileImagePicker(EProfileImageType type, LLHandle *handle); - ~LLProfileImagePicker(); - void notify(const std::vector& filenames) override; - -private: - LLHandle *mHandle; - EProfileImageType mType; -}; - -LLProfileImagePicker::LLProfileImagePicker(EProfileImageType type, LLHandle *handle) - : LLFilePickerThread(LLFilePicker::FFLOAD_IMAGE), - mHandle(handle), - mType(type) -{ -} - -LLProfileImagePicker::~LLProfileImagePicker() -{ - delete mHandle; -} - -void LLProfileImagePicker::notify(const std::vector& filenames) -{ - if (mHandle->isDead()) - { - return; - } - if (filenames.empty()) - { - return; - } - std::string file_path = filenames[0]; - if (file_path.empty()) - { - return; - } - - // generate a temp texture file for coroutine - std::string temp_file = gDirUtilp->getTempFilename(); - U32 codec = LLImageBase::getCodecFromExtension(gDirUtilp->getExtension(file_path)); - const S32 MAX_DIM = 256; - if (!LLViewerTextureList::createUploadFile(file_path, temp_file, codec, MAX_DIM)) - { - LLSD notif_args; - notif_args["REASON"] = LLImage::getLastThreadError().c_str(); - LLNotificationsUtil::add("CannotUploadTexture", notif_args); - LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)mType << ", " << notif_args["REASON"].asString() << LL_ENDL; - return; - } - - std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP); - if (cap_url.empty()) - { - LLSD args; - args["CAPABILITY"] = PROFILE_IMAGE_UPLOAD_CAP; - LLNotificationsUtil::add("RegionCapabilityRequestError", args); - LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)mType << ", no cap found" << LL_ENDL; - return; - } - - switch (mType) - { - case PROFILE_IMAGE_SL: - { - LLPanelProfileSecondLife* panel = static_cast(mHandle->get()); - panel->setProfileImageUploading(true); - } - break; - case PROFILE_IMAGE_FL: - { - LLPanelProfileFirstLife* panel = static_cast(mHandle->get()); - panel->setProfileImageUploading(true); - } - break; - } - - LLCoros::instance().launch("postAgentUserImageCoro", - boost::bind(post_profile_image_coro, cap_url, mType, temp_file, mHandle)); - - mHandle = nullptr; // transferred to post_profile_image_coro -} - -void LLPanelProfileSecondLife::onCommitMenu(const LLSD& userdata) -{ - const std::string item_name = userdata.asString(); - const LLUUID agent_id = getAvatarId(); - // todo: consider moving this into LLAvatarActions::onCommit(name, id) - // and making all other flaoters, like people menu do the same - if (item_name == "im") - { - LLAvatarActions::startIM(agent_id); - } - else if (item_name == "offer_teleport") - { - LLAvatarActions::offerTeleport(agent_id); - } - else if (item_name == "request_teleport") - { - LLAvatarActions::teleportRequest(agent_id); - } - else if (item_name == "voice_call") - { - LLAvatarActions::startCall(agent_id); - } - else if (item_name == "chat_history") - { - LLAvatarActions::viewChatHistory(agent_id); - } - else if (item_name == "add_friend") - { - LLAvatarActions::requestFriendshipDialog(agent_id); - } - else if (item_name == "remove_friend") - { - LLAvatarActions::removeFriendDialog(agent_id); - } - else if (item_name == "invite_to_group") - { - LLAvatarActions::inviteToGroup(agent_id); - } - else if (item_name == "can_show_on_map") - { - LLAvatarActions::showOnMap(agent_id); - } - else if (item_name == "share") - { - LLAvatarActions::share(agent_id); - } - else if (item_name == "pay") - { - LLAvatarActions::pay(agent_id); - } - else if (item_name == "toggle_block_agent") - { - LLAvatarActions::toggleBlock(agent_id); - } - else if (item_name == "copy_user_id") - { - LLWString wstr = utf8str_to_wstring(getAvatarId().asString()); - LLClipboard::instance().copyToClipboard(wstr, 0, wstr.size()); - } - else if (item_name == "agent_permissions") - { - onShowAgentPermissionsDialog(); - } - else if (item_name == "copy_display_name" - || item_name == "copy_username") - { - LLAvatarName av_name; - if (!LLAvatarNameCache::get(getAvatarId(), &av_name)) - { - // shouldn't happen, option is supposed to be invisible while name is fetching - LL_WARNS() << "Failed to get agent data" << LL_ENDL; - return; - } - LLWString wstr; - if (item_name == "copy_display_name") - { - wstr = utf8str_to_wstring(av_name.getDisplayName(true)); - } - else if (item_name == "copy_username") - { - wstr = utf8str_to_wstring(av_name.getUserName()); - } - LLClipboard::instance().copyToClipboard(wstr, 0, wstr.size()); - } - else if (item_name == "edit_display_name") - { - LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCacheSetName, this, _1, _2)); - LLFirstUse::setDisplayName(false); - } - else if (item_name == "edit_partner") - { - std::string url = "https://[GRID]/my/account/partners.php"; - LLSD subs; - url = LLWeb::expandURLSubstitutions(url, subs); - LLUrlAction::openURL(url); - } - else if (item_name == "upload_photo") - { - (new LLProfileImagePicker(PROFILE_IMAGE_SL, new LLHandle(LLPanel::getHandle())))->getFile(); - - LLFloater* floaterp = mFloaterTexturePickerHandle.get(); - if (floaterp) - { - floaterp->closeFloater(); - } - } - else if (item_name == "change_photo") - { - onShowTexturePicker(); - } - else if (item_name == "remove_photo") - { - onCommitProfileImage(LLUUID::null); - - LLFloater* floaterp = mFloaterTexturePickerHandle.get(); - if (floaterp) - { - floaterp->closeFloater(); - } - } -} - -bool LLPanelProfileSecondLife::onEnableMenu(const LLSD& userdata) -{ - const std::string item_name = userdata.asString(); - const LLUUID agent_id = getAvatarId(); - if (item_name == "offer_teleport" || item_name == "request_teleport") - { - return LLAvatarActions::canOfferTeleport(agent_id); - } - else if (item_name == "voice_call") - { - return mVoiceStatus; - } - else if (item_name == "chat_history") - { - return LLLogChat::isTranscriptExist(agent_id); - } - else if (item_name == "add_friend") - { - return !LLAvatarActions::isFriend(agent_id); - } - else if (item_name == "remove_friend") - { - return LLAvatarActions::isFriend(agent_id); - } - else if (item_name == "can_show_on_map") - { - return (LLAvatarTracker::instance().isBuddyOnline(agent_id) && is_agent_mappable(agent_id)) - || gAgent.isGodlike(); - } - else if (item_name == "toggle_block_agent") - { - return LLAvatarActions::canBlock(agent_id); - } - else if (item_name == "agent_permissions") - { - return LLAvatarActions::isFriend(agent_id); - } - else if (item_name == "copy_display_name" - || item_name == "copy_username") - { - return !mAvatarNameCacheConnection.connected(); - } - else if (item_name == "upload_photo" - || item_name == "change_photo") - { - std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP); - return !cap_url.empty() && !mWaitingForImageUpload && getIsLoaded(); - } - else if (item_name == "remove_photo") - { - std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); - return mSecondLifePic->getImageAssetId().notNull() && !cap_url.empty() && !mWaitingForImageUpload && getIsLoaded(); - } - - return false; -} - -bool LLPanelProfileSecondLife::onCheckMenu(const LLSD& userdata) -{ - const std::string item_name = userdata.asString(); - const LLUUID agent_id = getAvatarId(); - if (item_name == "toggle_block_agent") - { - return LLAvatarActions::isBlocked(agent_id); - } - return 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"); -} - -void LLPanelProfileSecondLife::setDescriptionText(const std::string &text) -{ - mSaveDescriptionChanges->setEnabled(false); - mDiscardDescriptionChanges->setEnabled(false); - mHasUnsavedDescriptionChanges = false; - - mDescriptionText = text; - mDescriptionEdit->setValue(mDescriptionText); -} - -void LLPanelProfileSecondLife::onSetDescriptionDirty() -{ - mSaveDescriptionChanges->setEnabled(true); - mDiscardDescriptionChanges->setEnabled(true); - mHasUnsavedDescriptionChanges = true; -} - -void LLPanelProfileSecondLife::onShowInSearchCallback() -{ - bool value = mShowInSearchCombo->getValue().asInteger(); - if (value == mAllowPublish) - return; - - mAllowPublish = value; - saveAgentUserInfoCoro("allow_publish", value); -} - -void LLPanelProfileSecondLife::onHideAgeCallback() -{ - bool value = mHideAgeCombo->getValue().asInteger(); - if (value == mHideAge) - return; - - mHideAge = value; - saveAgentUserInfoCoro("hide_age", value); -} - -void LLPanelProfileSecondLife::onSaveDescriptionChanges() -{ - mDescriptionText = mDescriptionEdit->getValue().asString(); - saveAgentUserInfoCoro("sl_about_text", mDescriptionText); - - mSaveDescriptionChanges->setEnabled(false); - mDiscardDescriptionChanges->setEnabled(false); - mHasUnsavedDescriptionChanges = false; -} - -void LLPanelProfileSecondLife::onDiscardDescriptionChanges() -{ - setDescriptionText(mDescriptionText); -} - -void LLPanelProfileSecondLife::onShowAgentPermissionsDialog() -{ - LLFloater *floater = mFloaterPermissionsHandle.get(); - if (!floater) - { - LLFloater* parent_floater = gFloaterView->getParentFloater(this); - if (parent_floater) - { - LLFloaterProfilePermissions * perms = new LLFloaterProfilePermissions(parent_floater, getAvatarId()); - mFloaterPermissionsHandle = perms->getHandle(); - perms->openFloater(); - perms->setVisibleAndFrontmost(true); - - parent_floater->addDependentFloater(mFloaterPermissionsHandle); - } - } - else // already open - { - floater->setMinimized(false); - floater->setVisibleAndFrontmost(true); - } -} - -void LLPanelProfileSecondLife::onShowAgentProfileTexture() -{ - if (!getIsLoaded()) - { - return; - } - - LLFloater *floater = mFloaterProfileTextureHandle.get(); - if (!floater) - { - LLFloater* parent_floater = gFloaterView->getParentFloater(this); - if (parent_floater) - { - LLFloaterProfileTexture * texture_view = new LLFloaterProfileTexture(parent_floater); - mFloaterProfileTextureHandle = texture_view->getHandle(); - if (mSecondLifePic->getImageAssetId().notNull()) - { - texture_view->loadAsset(mSecondLifePic->getImageAssetId()); - } - else - { - texture_view->resetAsset(); - } - texture_view->openFloater(); - texture_view->setVisibleAndFrontmost(true); - - parent_floater->addDependentFloater(mFloaterProfileTextureHandle); - } - } - else // already open - { - LLFloaterProfileTexture * texture_view = dynamic_cast(floater); - texture_view->setMinimized(false); - texture_view->setVisibleAndFrontmost(true); - if (mSecondLifePic->getImageAssetId().notNull()) - { - texture_view->loadAsset(mSecondLifePic->getImageAssetId()); - } - else - { - texture_view->resetAsset(); - } - } -} - -void LLPanelProfileSecondLife::onShowTexturePicker() -{ - LLFloater* floaterp = mFloaterTexturePickerHandle.get(); - - // Show the dialog - if (!floaterp) - { - LLFloater* parent_floater = gFloaterView->getParentFloater(this); - if (parent_floater) - { - // because inventory construction is somewhat slow - getWindow()->setCursor(UI_CURSOR_WAIT); - LLFloaterTexturePicker* texture_floaterp = new LLFloaterTexturePicker( - this, - mSecondLifePic->getImageAssetId(), - LLUUID::null, - mSecondLifePic->getImageAssetId(), - false, - false, - "SELECT PHOTO", - PERM_NONE, - PERM_NONE, - false, - NULL, - PICK_TEXTURE); - - mFloaterTexturePickerHandle = texture_floaterp->getHandle(); - - texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID&, const LLUUID&) - { - if (op == LLTextureCtrl::TEXTURE_SELECT) - { - onCommitProfileImage(asset_id); - } - }); - texture_floaterp->setLocalTextureEnabled(false); - texture_floaterp->setBakeTextureEnabled(false); - texture_floaterp->setCanApply(false, true, false); - - parent_floater->addDependentFloater(mFloaterTexturePickerHandle); - - texture_floaterp->openFloater(); - texture_floaterp->setFocus(true); - } - } - else - { - floaterp->setMinimized(false); - floaterp->setVisibleAndFrontmost(true); - } -} - -void LLPanelProfileSecondLife::onCommitProfileImage(const LLUUID& id) -{ - if (mSecondLifePic->getImageAssetId() == id) - return; - - std::function callback = [id](bool result) - { - if (result) - { - LLAvatarIconIDCache::getInstance()->add(gAgentID, id); - // Should trigger callbacks in icon controls (or request Legacy) - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(gAgentID); - } - }; - - if (!saveAgentUserInfoCoro("sl_image_id", id, callback)) - return; - - mSecondLifePic->setValue(id); - - LLFloater *floater = mFloaterProfileTextureHandle.get(); - if (floater) - { - LLFloaterProfileTexture * texture_view = dynamic_cast(floater); - if (id == LLUUID::null) - { - texture_view->resetAsset(); - } - else - { - texture_view->loadAsset(id); - } - } -} - -////////////////////////////////////////////////////////////////////////// -// 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() -{ - mWebBrowser = getChild("profile_html"); - mWebBrowser->addObserver(this); - mWebBrowser->setHomePageUrl("about:blank"); - - return true; -} - -void LLPanelProfileWeb::resetData() -{ - mWebBrowser->navigateHome(); -} - -void LLPanelProfileWeb::updateData() -{ - LLUUID avatar_id = getAvatarId(); - if (!getStarted() && avatar_id.notNull() && !mURLWebProfile.empty()) - { - setIsLoading(); - - 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, true); - if (mURLWebProfile.empty()) - { - return; - } - - //if the tab was opened before name was resolved, load the panel now - 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::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) -{ - switch(event) - { - case MEDIA_EVENT_STATUS_TEXT_CHANGED: - childSetValue("status_text", LLSD( self->getStatusText() ) ); - 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)) ); - - setLoaded(); - } - break; - - default: - // Having a default case makes the compiler happy. - break; - } -} - - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLPanelProfileFirstLife::LLPanelProfileFirstLife() - : LLPanelProfilePropertiesProcessorTab() - , mHasUnsavedChanges(false) -{ -} - -LLPanelProfileFirstLife::~LLPanelProfileFirstLife() -{ -} - -bool LLPanelProfileFirstLife::postBuild() -{ - mDescriptionEdit = getChild("fl_description_edit"); - mPicture = getChild("real_world_pic"); - - mUploadPhoto = getChild("fl_upload_image"); - mChangePhoto = getChild("fl_change_image"); - mRemovePhoto = getChild("fl_remove_image"); - mSaveChanges = getChild("fl_save_changes"); - mDiscardChanges = getChild("fl_discard_changes"); - - mUploadPhoto->setCommitCallback([this](LLUICtrl*, void*) { onUploadPhoto(); }, nullptr); - mChangePhoto->setCommitCallback([this](LLUICtrl*, void*) { onChangePhoto(); }, nullptr); - mRemovePhoto->setCommitCallback([this](LLUICtrl*, void*) { onRemovePhoto(); }, nullptr); - mSaveChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveDescriptionChanges(); }, nullptr); - mDiscardChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardDescriptionChanges(); }, nullptr); - mDescriptionEdit->setKeystrokeCallback([this](LLTextEditor* caller) { onSetDescriptionDirty(); }); - - return true; -} - -void LLPanelProfileFirstLife::onOpen(const LLSD& key) -{ - LLPanelProfileTab::onOpen(key); - - if (!getSelfProfile()) - { - // Otherwise as the only focusable element it will be selected - mDescriptionEdit->setTabStop(false); - } - - resetData(); -} - -void LLPanelProfileFirstLife::setProfileImageUploading(bool loading) -{ - mUploadPhoto->setEnabled(!loading); - mChangePhoto->setEnabled(!loading); - mRemovePhoto->setEnabled(!loading && mPicture->getImageAssetId().notNull()); - - LLLoadingIndicator* indicator = getChild("image_upload_indicator"); - indicator->setVisible(loading); - if (loading) - { - indicator->start(); - } - else - { - indicator->stop(); - } -} - -void LLPanelProfileFirstLife::setProfileImageUploaded(const LLUUID &image_asset_id) -{ - mPicture->setValue(image_asset_id); - setProfileImageUploading(false); -} - -void LLPanelProfileFirstLife::commitUnsavedChanges() -{ - if (mHasUnsavedChanges) - { - onSaveDescriptionChanges(); - } -} - -void LLPanelProfileFirstLife::onUploadPhoto() -{ - (new LLProfileImagePicker(PROFILE_IMAGE_FL, new LLHandle(LLPanel::getHandle())))->getFile(); - - LLFloater* floaterp = mFloaterTexturePickerHandle.get(); - if (floaterp) - { - floaterp->closeFloater(); - } -} - -void LLPanelProfileFirstLife::onChangePhoto() -{ - LLFloater* floaterp = mFloaterTexturePickerHandle.get(); - - // Show the dialog - if (!floaterp) - { - LLFloater* parent_floater = gFloaterView->getParentFloater(this); - if (parent_floater) - { - // because inventory construction is somewhat slow - getWindow()->setCursor(UI_CURSOR_WAIT); - LLFloaterTexturePicker* texture_floaterp = new LLFloaterTexturePicker( - this, - mPicture->getImageAssetId(), - LLUUID::null, - mPicture->getImageAssetId(), - false, - false, - "SELECT PHOTO", - PERM_NONE, - PERM_NONE, - false, - NULL, - PICK_TEXTURE); - - mFloaterTexturePickerHandle = texture_floaterp->getHandle(); - - texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID&, const LLUUID&) - { - if (op == LLTextureCtrl::TEXTURE_SELECT) - { - onCommitPhoto(asset_id); - } - }); - texture_floaterp->setLocalTextureEnabled(false); - texture_floaterp->setCanApply(false, true, false); - - parent_floater->addDependentFloater(mFloaterTexturePickerHandle); - - texture_floaterp->openFloater(); - texture_floaterp->setFocus(true); - } - } - else - { - floaterp->setMinimized(false); - floaterp->setVisibleAndFrontmost(true); - } -} - -void LLPanelProfileFirstLife::onRemovePhoto() -{ - onCommitPhoto(LLUUID::null); - - LLFloater* floaterp = mFloaterTexturePickerHandle.get(); - if (floaterp) - { - floaterp->closeFloater(); - } -} - -void LLPanelProfileFirstLife::onCommitPhoto(const LLUUID& id) -{ - if (mPicture->getImageAssetId() == id) - return; - - if (!saveAgentUserInfoCoro("fl_image_id", id)) - return; - - mPicture->setValue(id); - - mRemovePhoto->setEnabled(id.notNull()); -} - -void LLPanelProfileFirstLife::setDescriptionText(const std::string &text) -{ - mSaveChanges->setEnabled(false); - mDiscardChanges->setEnabled(false); - mHasUnsavedChanges = false; - - mCurrentDescription = text; - mDescriptionEdit->setValue(mCurrentDescription); -} - -void LLPanelProfileFirstLife::onSetDescriptionDirty() -{ - mSaveChanges->setEnabled(true); - mDiscardChanges->setEnabled(true); - mHasUnsavedChanges = true; -} - -void LLPanelProfileFirstLife::onSaveDescriptionChanges() -{ - mCurrentDescription = mDescriptionEdit->getValue().asString(); - saveAgentUserInfoCoro("fl_about_text", mCurrentDescription); - - mSaveChanges->setEnabled(false); - mDiscardChanges->setEnabled(false); - mHasUnsavedChanges = false; -} - -void LLPanelProfileFirstLife::onDiscardDescriptionChanges() -{ - setDescriptionText(mCurrentDescription); -} - -void LLPanelProfileFirstLife::processProperties(void* data, EAvatarProcessorType type) -{ - if (APT_PROPERTIES == type) - { - LLAvatarData* avatar_data = static_cast(data); - if (avatar_data && getAvatarId() == avatar_data->avatar_id) - { - processProperties(avatar_data); - } - } -} - -void LLPanelProfileFirstLife::processProperties(const LLAvatarData* avatar_data) -{ - setDescriptionText(avatar_data->fl_about_text); - - mPicture->setValue(avatar_data->fl_image_id); - - setLoaded(); -} - -void LLPanelProfileFirstLife::resetData() -{ - setDescriptionText(std::string()); - mPicture->setValue(LLUUID::null); - - mUploadPhoto->setVisible(getSelfProfile()); - mChangePhoto->setVisible(getSelfProfile()); - mRemovePhoto->setVisible(getSelfProfile()); - mSaveChanges->setVisible(getSelfProfile()); - mDiscardChanges->setVisible(getSelfProfile()); -} - -void LLPanelProfileFirstLife::setLoaded() -{ - LLPanelProfileTab::setLoaded(); - - if (getSelfProfile()) - { - mDescriptionEdit->setEnabled(true); - mPicture->setEnabled(true); - mRemovePhoto->setEnabled(mPicture->getImageAssetId().notNull()); - } -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// - -LLPanelProfileNotes::LLPanelProfileNotes() -: LLPanelProfilePropertiesProcessorTab() - , mHasUnsavedChanges(false) -{ - -} - -LLPanelProfileNotes::~LLPanelProfileNotes() -{ -} - -void LLPanelProfileNotes::commitUnsavedChanges() -{ - if (mHasUnsavedChanges) - { - onSaveNotesChanges(); - } -} - -bool LLPanelProfileNotes::postBuild() -{ - mNotesEditor = getChild("notes_edit"); - mSaveChanges = getChild("notes_save_changes"); - mDiscardChanges = getChild("notes_discard_changes"); - - mSaveChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveNotesChanges(); }, nullptr); - mDiscardChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardNotesChanges(); }, nullptr); - mNotesEditor->setKeystrokeCallback([this](LLTextEditor* caller) { onSetNotesDirty(); }); - - return true; -} - -void LLPanelProfileNotes::onOpen(const LLSD& key) -{ - LLPanelProfileTab::onOpen(key); - - resetData(); -} - -void LLPanelProfileNotes::setNotesText(const std::string &text) -{ - mSaveChanges->setEnabled(false); - mDiscardChanges->setEnabled(false); - mHasUnsavedChanges = false; - - mCurrentNotes = text; - mNotesEditor->setValue(mCurrentNotes); -} - -void LLPanelProfileNotes::onSetNotesDirty() -{ - mSaveChanges->setEnabled(true); - mDiscardChanges->setEnabled(true); - mHasUnsavedChanges = true; -} - -void LLPanelProfileNotes::onSaveNotesChanges() -{ - mCurrentNotes = mNotesEditor->getValue().asString(); - saveAgentUserInfoCoro("notes", mCurrentNotes); - - mSaveChanges->setEnabled(false); - mDiscardChanges->setEnabled(false); - mHasUnsavedChanges = false; -} - -void LLPanelProfileNotes::onDiscardNotesChanges() -{ - setNotesText(mCurrentNotes); -} - -void LLPanelProfileNotes::processProperties(void* data, EAvatarProcessorType type) -{ - if (APT_PROPERTIES == type) - { - LLAvatarData* avatar_data = static_cast(data); - if (avatar_data && getAvatarId() == avatar_data->avatar_id) - { - processProperties(avatar_data); - } - } -} - -void LLPanelProfileNotes::processProperties(const LLAvatarData* avatar_data) -{ - setNotesText(avatar_data->notes); - mNotesEditor->setEnabled(true); - setLoaded(); -} - -void LLPanelProfileNotes::resetData() -{ - resetLoading(); - setNotesText(std::string()); -} - - -////////////////////////////////////////////////////////////////////////// -// LLPanelProfile - -LLPanelProfile::LLPanelProfile() - : LLPanelProfileTab() -{ -} - -LLPanelProfile::~LLPanelProfile() -{ -} - -bool LLPanelProfile::postBuild() -{ - return true; -} - -void LLPanelProfile::onTabChange() -{ - LLPanelProfileTab* active_panel = dynamic_cast(mTabContainer->getCurrentPanel()); - if (active_panel) - { - active_panel->updateData(); - } -} - -void LLPanelProfile::onOpen(const LLSD& key) -{ - LLUUID avatar_id = key["id"].asUUID(); - - // Don't reload the same profile - if (getAvatarId() == avatar_id) - { - return; - } - - LLPanelProfileTab::onOpen(avatar_id); - - mTabContainer = getChild("panel_profile_tabs"); - mPanelSecondlife = findChild(PANEL_SECONDLIFE); - mPanelWeb = findChild(PANEL_WEB); - mPanelPicks = findChild(PANEL_PICKS); - mPanelClassifieds = findChild(PANEL_CLASSIFIEDS); - mPanelFirstlife = findChild(PANEL_FIRSTLIFE); - mPanelNotes = findChild(PANEL_NOTES); - - mPanelSecondlife->onOpen(avatar_id); - mPanelWeb->onOpen(avatar_id); - mPanelPicks->onOpen(avatar_id); - mPanelClassifieds->onOpen(avatar_id); - mPanelFirstlife->onOpen(avatar_id); - mPanelNotes->onOpen(avatar_id); - - // Always request the base profile info - resetLoading(); - updateData(); - - // Some tabs only request data when opened - mTabContainer->setCommitCallback(boost::bind(&LLPanelProfile::onTabChange, this)); -} - -void LLPanelProfile::updateData() -{ - LLUUID avatar_id = getAvatarId(); - // Todo: getIsloading functionality needs to be expanded to - // include 'inited' or 'data_provided' state to not rerequest - if (!getStarted() && avatar_id.notNull()) - { - setIsLoading(); - - mPanelSecondlife->setIsLoading(); - mPanelPicks->setIsLoading(); - mPanelFirstlife->setIsLoading(); - mPanelNotes->setIsLoading(); - - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(getAvatarId()); - } -} - -void LLPanelProfile::refreshName() -{ - mPanelSecondlife->refreshName(); -} - -void LLPanelProfile::createPick(const LLPickData &data) -{ - mTabContainer->selectTabPanel(mPanelPicks); - mPanelPicks->createPick(data); -} - -void LLPanelProfile::showPick(const LLUUID& pick_id) -{ - if (pick_id.notNull()) - { - mPanelPicks->selectPick(pick_id); - } - mTabContainer->selectTabPanel(mPanelPicks); -} - -bool LLPanelProfile::isPickTabSelected() -{ - return (mTabContainer->getCurrentPanel() == mPanelPicks); -} - -bool LLPanelProfile::isNotesTabSelected() -{ - return (mTabContainer->getCurrentPanel() == mPanelNotes); -} - -bool LLPanelProfile::hasUnsavedChanges() -{ - return mPanelSecondlife->hasUnsavedChanges() - || mPanelPicks->hasUnsavedChanges() - || mPanelClassifieds->hasUnsavedChanges() - || mPanelFirstlife->hasUnsavedChanges() - || mPanelNotes->hasUnsavedChanges(); -} - -bool LLPanelProfile::hasUnpublishedClassifieds() -{ - return mPanelClassifieds->hasNewClassifieds(); -} - -void LLPanelProfile::commitUnsavedChanges() -{ - mPanelSecondlife->commitUnsavedChanges(); - mPanelPicks->commitUnsavedChanges(); - mPanelClassifieds->commitUnsavedChanges(); - mPanelFirstlife->commitUnsavedChanges(); - mPanelNotes->commitUnsavedChanges(); -} - -void LLPanelProfile::showClassified(const LLUUID& classified_id, bool edit) -{ - if (classified_id.notNull()) - { - mPanelClassifieds->selectClassified(classified_id, edit); - } - mTabContainer->selectTabPanel(mPanelClassifieds); -} - -void LLPanelProfile::createClassified() -{ - mPanelClassifieds->createClassified(); - mTabContainer->selectTabPanel(mPanelClassifieds); -} - +/** +* @file llpanelprofile.cpp +* @brief Profile panel implementation +* +* $LicenseInfo:firstyear=2022&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2022, 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" + +// Common +#include "llavatarnamecache.h" +#include "llsdutil.h" +#include "llslurl.h" +#include "lldateutil.h" //ageFromDate + +// UI +#include "llavatariconctrl.h" +#include "llclipboard.h" +#include "llcheckboxctrl.h" +#include "llcombobox.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 "lltooldraganddrop.h" +#include "llgrouplist.h" +#include "llurlaction.h" + +// Image +#include "llimagej2c.h" + +// Newview +#include "llagent.h" //gAgent +#include "llagentpicksinfo.h" +#include "llavataractions.h" +#include "llavatarpropertiesprocessor.h" +#include "llcallingcard.h" +#include "llcommandhandler.h" +#include "llfloaterprofiletexture.h" +#include "llfloaterreg.h" +#include "llfloaterreporter.h" +#include "llfilepicker.h" +#include "llfirstuse.h" +#include "llgroupactions.h" +#include "lllogchat.h" +#include "llmutelist.h" +#include "llnotificationsutil.h" +#include "llpanelblockedlist.h" +#include "llpanelprofileclassifieds.h" +#include "llpanelprofilepicks.h" +#include "lltrans.h" +#include "llviewercontrol.h" +#include "llviewermenu.h" //is_agent_mappable +#include "llviewermenufile.h" +#include "llviewertexturelist.h" +#include "llvoiceclient.h" +#include "llweb.h" + + +static LLPanelInjector t_panel_profile_secondlife("panel_profile_secondlife"); +static LLPanelInjector t_panel_web("panel_profile_web"); +static LLPanelInjector t_panel_picks("panel_profile_picks"); +static LLPanelInjector t_panel_firstlife("panel_profile_firstlife"); +static LLPanelInjector t_panel_notes("panel_profile_notes"); +static LLPanelInjector 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_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"; +static const std::string PANEL_PROFILE_VIEW = "panel_profile_view"; + +static const std::string PROFILE_PROPERTIES_CAP = "AgentProfile"; +static const std::string PROFILE_IMAGE_UPLOAD_CAP = "UploadAgentProfileImage"; + + +////////////////////////////////////////////////////////////////////////// + +LLUUID post_profile_image(std::string cap_url, const LLSD &first_data, std::string path_to_image, LLHandle *handle) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("post_profile_image_coro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpHeaders::ptr_t httpHeaders; + + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + httpOpts->setFollowRedirects(true); + + LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, first_data, httpOpts, httpHeaders); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + // todo: notification? + LL_WARNS("AvatarProperties") << "Failed to get uploader cap " << status.toString() << LL_ENDL; + return LLUUID::null; + } + if (!result.has("uploader")) + { + // todo: notification? + LL_WARNS("AvatarProperties") << "Failed to get uploader cap, response contains no data." << LL_ENDL; + return LLUUID::null; + } + std::string uploader_cap = result["uploader"].asString(); + if (uploader_cap.empty()) + { + LL_WARNS("AvatarProperties") << "Failed to get uploader cap, cap invalid." << LL_ENDL; + return LLUUID::null; + } + + // Upload the image + LLCore::HttpRequest::ptr_t uploaderhttpRequest(new LLCore::HttpRequest); + LLCore::HttpHeaders::ptr_t uploaderhttpHeaders(new LLCore::HttpHeaders); + LLCore::HttpOptions::ptr_t uploaderhttpOpts(new LLCore::HttpOptions); + S64 length; + + { + llifstream instream(path_to_image.c_str(), std::iostream::binary | std::iostream::ate); + if (!instream.is_open()) + { + LL_WARNS("AvatarProperties") << "Failed to open file " << path_to_image << LL_ENDL; + return LLUUID::null; + } + length = instream.tellg(); + } + + uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, "application/jp2"); // optional + uploaderhttpHeaders->append(HTTP_OUT_HEADER_CONTENT_LENGTH, llformat("%d", length)); // required! + uploaderhttpOpts->setFollowRedirects(true); + + result = httpAdapter->postFileAndSuspend(uploaderhttpRequest, uploader_cap, path_to_image, uploaderhttpOpts, uploaderhttpHeaders); + + httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + LL_DEBUGS("AvatarProperties") << result << LL_ENDL; + + if (!status) + { + LL_WARNS("AvatarProperties") << "Failed to upload image " << status.toString() << LL_ENDL; + return LLUUID::null; + } + + if (result["state"].asString() != "complete") + { + if (result.has("message")) + { + LL_WARNS("AvatarProperties") << "Failed to upload image, state " << result["state"] << " message: " << result["message"] << LL_ENDL; + } + else + { + LL_WARNS("AvatarProperties") << "Failed to upload image " << result << LL_ENDL; + } + return LLUUID::null; + } + + return result["new_asset"].asUUID(); +} + +enum EProfileImageType +{ + PROFILE_IMAGE_SL, + PROFILE_IMAGE_FL, +}; + +void post_profile_image_coro(std::string cap_url, EProfileImageType type, std::string path_to_image, LLHandle *handle) +{ + LLSD data; + switch (type) + { + case PROFILE_IMAGE_SL: + data["profile-image-asset"] = "sl_image_id"; + break; + case PROFILE_IMAGE_FL: + data["profile-image-asset"] = "fl_image_id"; + break; + } + + LLUUID result = post_profile_image(cap_url, data, path_to_image, handle); + + // reset loading indicator + if (!handle->isDead()) + { + switch (type) + { + case PROFILE_IMAGE_SL: + { + LLPanelProfileSecondLife* panel = static_cast(handle->get()); + if (result.notNull()) + { + panel->setProfileImageUploaded(result); + } + else + { + // failure, just stop progress indicator + panel->setProfileImageUploading(false); + } + break; + } + case PROFILE_IMAGE_FL: + { + LLPanelProfileFirstLife* panel = static_cast(handle->get()); + if (result.notNull()) + { + panel->setProfileImageUploaded(result); + } + else + { + // failure, just stop progress indicator + panel->setProfileImageUploading(false); + } + break; + } + } + } + + if (type == PROFILE_IMAGE_SL && result.notNull()) + { + LLAvatarIconIDCache::getInstance()->add(gAgentID, result); + // Should trigger callbacks in icon controls + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(gAgentID); + } + + // Cleanup + LLFile::remove(path_to_image); + delete handle; +} + +////////////////////////////////////////////////////////////////////////// +// 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, + const std::string& grid, + 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; + + +////////////////////////////////////////////////////////////////////////// +// LLAgentHandler + +class LLAgentHandler : public LLCommandHandler +{ +public: + // requires trusted browser to trigger + LLAgentHandler() : LLCommandHandler("agent", UNTRUSTED_THROTTLE) { } + + virtual bool canHandleUntrusted( + const LLSD& params, + const LLSD& query_map, + LLMediaCtrl* web, + const std::string& nav_type) + { + if (params.size() < 2) + { + return true; // don't block, will fail later + } + + if (nav_type == NAV_TYPE_CLICKED + || nav_type == NAV_TYPE_EXTERNAL) + { + return true; + } + + const std::string verb = params[1].asString(); + if (verb == "about" || verb == "inspect" || verb == "reportAbuse") + { + return true; + } + return false; + } + + bool handle(const LLSD& params, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) + { + if (params.size() < 2) return false; + LLUUID avatar_id; + if (!avatar_id.set(params[0], false)) + { + return false; + } + + const std::string verb = params[1].asString(); + if (verb == "about") + { + LLAvatarActions::showProfile(avatar_id); + return true; + } + + if (verb == "inspect") + { + LLFloaterReg::showInstance("inspect_avatar", LLSD().with("avatar_id", avatar_id)); + return true; + } + + if (verb == "im") + { + LLAvatarActions::startIM(avatar_id); + return true; + } + + if (verb == "pay") + { + if (!LLUI::getInstance()->mSettingGroups["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; + } + + if (verb == "block") + { + if (params.size() > 2) + { + 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; + } + + // reportAbuse is here due to convoluted avatar handling + // in LLScrollListCtrl and LLTextBase + if (verb == "reportAbuse" && web == NULL) + { + LLAvatarName av_name; + if (LLAvatarNameCache::get(avatar_id, &av_name)) + { + LLFloaterReporter::showFromAvatar(avatar_id, av_name.getCompleteName()); + } + else + { + LLFloaterReporter::showFromAvatar(avatar_id, "not avaliable"); + } + return true; + } + return false; + } +}; +LLAgentHandler gAgentHandler; + + +///---------------------------------------------------------------------------- +/// LLFloaterProfilePermissions +///---------------------------------------------------------------------------- + +class LLFloaterProfilePermissions + : public LLFloater + , public LLFriendObserver +{ +public: + LLFloaterProfilePermissions(LLView * owner, const LLUUID &avatar_id); + ~LLFloaterProfilePermissions(); + bool postBuild() override; + void onOpen(const LLSD& key) override; + void draw() override; + void changed(U32 mask) override; // LLFriendObserver + + void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); + bool hasUnsavedChanges() { return mHasUnsavedPermChanges; } + + void onApplyRights(); + +private: + void fillRightsData(); + void rightsConfirmationCallback(const LLSD& notification, const LLSD& response); + void confirmModifyRights(bool grant); + void onCommitSeeOnlineRights(); + void onCommitEditRights(); + void onCancel(); + + LLTextBase* mDescription; + LLCheckBoxCtrl* mOnlineStatus; + LLCheckBoxCtrl* mMapRights; + LLCheckBoxCtrl* mEditObjectRights; + LLButton* mOkBtn; + LLButton* mCancelBtn; + + LLUUID mAvatarID; + F32 mContextConeOpacity; + bool mHasUnsavedPermChanges; + LLHandle mOwnerHandle; + + boost::signals2::connection mAvatarNameCacheConnection; +}; + +LLFloaterProfilePermissions::LLFloaterProfilePermissions(LLView * owner, const LLUUID &avatar_id) + : LLFloater(LLSD()) + , mAvatarID(avatar_id) + , mContextConeOpacity(0.0f) + , mHasUnsavedPermChanges(false) + , mOwnerHandle(owner->getHandle()) +{ + buildFromFile("floater_profile_permissions.xml"); +} + +LLFloaterProfilePermissions::~LLFloaterProfilePermissions() +{ + mAvatarNameCacheConnection.disconnect(); + if (mAvatarID.notNull()) + { + LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this); + } +} + +bool LLFloaterProfilePermissions::postBuild() +{ + mDescription = getChild("perm_description"); + mOnlineStatus = getChild("online_check"); + mMapRights = getChild("map_check"); + mEditObjectRights = getChild("objects_check"); + mOkBtn = getChild("perms_btn_ok"); + mCancelBtn = getChild("perms_btn_cancel"); + + mOnlineStatus->setCommitCallback([this](LLUICtrl*, void*) { onCommitSeeOnlineRights(); }, nullptr); + mMapRights->setCommitCallback([this](LLUICtrl*, void*) { mHasUnsavedPermChanges = true; }, nullptr); + mEditObjectRights->setCommitCallback([this](LLUICtrl*, void*) { onCommitEditRights(); }, nullptr); + mOkBtn->setCommitCallback([this](LLUICtrl*, void*) { onApplyRights(); }, nullptr); + mCancelBtn->setCommitCallback([this](LLUICtrl*, void*) { onCancel(); }, nullptr); + + return true; +} + +void LLFloaterProfilePermissions::onOpen(const LLSD& key) +{ + if (LLAvatarActions::isFriend(mAvatarID)) + { + LLAvatarTracker::instance().addParticularFriendObserver(mAvatarID, this); + fillRightsData(); + } + + mCancelBtn->setFocus(true); + + mAvatarNameCacheConnection = LLAvatarNameCache::get(mAvatarID, boost::bind(&LLFloaterProfilePermissions::onAvatarNameCache, this, _1, _2)); +} + +void LLFloaterProfilePermissions::draw() +{ + // drawFrustum + LLView *owner = mOwnerHandle.get(); + static LLCachedControl max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f); + drawConeToOwner(mContextConeOpacity, max_opacity, owner); + LLFloater::draw(); +} + +void LLFloaterProfilePermissions::changed(U32 mask) +{ + if (mask != LLFriendObserver::ONLINE) + { + fillRightsData(); + } +} + +void LLFloaterProfilePermissions::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) +{ + mAvatarNameCacheConnection.disconnect(); + + LLStringUtil::format_map_t args; + args["[AGENT_NAME]"] = av_name.getDisplayName(); + std::string descritpion = getString("description_string", args); + mDescription->setValue(descritpion); +} + +void LLFloaterProfilePermissions::fillRightsData() +{ + const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); + // If true - we are viewing friend's profile, enable check boxes and set values. + if (relation) + { + S32 rights = relation->getRightsGrantedTo(); + + bool see_online = LLRelationship::GRANT_ONLINE_STATUS & rights; + mOnlineStatus->setValue(see_online); + mMapRights->setEnabled(see_online); + mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights); + mEditObjectRights->setValue(LLRelationship::GRANT_MODIFY_OBJECTS & rights); + } + else + { + closeFloater(); + LL_INFOS("ProfilePermissions") << "Floater closing since agent is no longer a friend" << LL_ENDL; + } +} + +void LLFloaterProfilePermissions::rightsConfirmationCallback(const LLSD& notification, + const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) // canceled + { + mEditObjectRights->setValue(!mEditObjectRights->getValue().asBoolean()); + } + else + { + mHasUnsavedPermChanges = true; + } +} + +void LLFloaterProfilePermissions::confirmModifyRights(bool grant) +{ + LLSD args; + args["NAME"] = LLSLURL("agent", mAvatarID, "completename").getSLURLString(); + LLNotificationsUtil::add(grant ? "GrantModifyRights" : "RevokeModifyRights", args, LLSD(), + boost::bind(&LLFloaterProfilePermissions::rightsConfirmationCallback, this, _1, _2)); +} + +void LLFloaterProfilePermissions::onCommitSeeOnlineRights() +{ + bool see_online = mOnlineStatus->getValue().asBoolean(); + mMapRights->setEnabled(see_online); + if (see_online) + { + const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); + if (relation) + { + S32 rights = relation->getRightsGrantedTo(); + mMapRights->setValue(LLRelationship::GRANT_MAP_LOCATION & rights); + } + else + { + closeFloater(); + LL_INFOS("ProfilePermissions") << "Floater closing since agent is no longer a friend" << LL_ENDL; + } + } + else + { + mMapRights->setValue(false); + } + mHasUnsavedPermChanges = true; +} + +void LLFloaterProfilePermissions::onCommitEditRights() +{ + const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); + + if (!buddy_relationship) + { + LL_WARNS("ProfilePermissions") << "Trying to modify rights for non-friend avatar. Closing floater." << LL_ENDL; + closeFloater(); + return; + } + + bool allow_modify_objects = mEditObjectRights->getValue().asBoolean(); + + // if modify objects checkbox clicked + if (buddy_relationship->isRightGrantedTo( + LLRelationship::GRANT_MODIFY_OBJECTS) != allow_modify_objects) + { + confirmModifyRights(allow_modify_objects); + } +} + +void LLFloaterProfilePermissions::onApplyRights() +{ + const LLRelationship* buddy_relationship = LLAvatarTracker::instance().getBuddyInfo(mAvatarID); + + if (!buddy_relationship) + { + LL_WARNS("ProfilePermissions") << "Trying to modify rights for non-friend avatar. Skipped." << LL_ENDL; + return; + } + + S32 rights = 0; + + if (mOnlineStatus->getValue().asBoolean()) + { + rights |= LLRelationship::GRANT_ONLINE_STATUS; + } + if (mMapRights->getValue().asBoolean()) + { + rights |= LLRelationship::GRANT_MAP_LOCATION; + } + if (mEditObjectRights->getValue().asBoolean()) + { + rights |= LLRelationship::GRANT_MODIFY_OBJECTS; + } + + LLAvatarPropertiesProcessor::getInstance()->sendFriendRights(mAvatarID, rights); + + closeFloater(); +} + +void LLFloaterProfilePermissions::onCancel() +{ + closeFloater(); +} + +////////////////////////////////////////////////////////////////////////// +// LLPanelProfileSecondLife + +LLPanelProfileSecondLife::LLPanelProfileSecondLife() + : LLPanelProfilePropertiesProcessorTab() + , mAvatarNameCacheConnection() + , mHasUnsavedDescriptionChanges(false) + , mWaitingForImageUpload(false) + , mAllowPublish(false) + , mHideAge(false) +{ +} + +LLPanelProfileSecondLife::~LLPanelProfileSecondLife() +{ + if (getAvatarId().notNull()) + { + LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this); + } + + if (LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this); + } + + if (mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection.disconnect(); + } +} + +bool LLPanelProfileSecondLife::postBuild() +{ + mGroupList = getChild("group_list"); + mShowInSearchCombo = getChild("show_in_search"); + mHideAgeCombo = getChild("hide_age"); + mSecondLifePic = getChild("2nd_life_pic"); + mSecondLifePicLayout = getChild("image_panel"); + mDescriptionEdit = getChild("sl_description_edit"); + mAgentActionMenuButton = getChild("agent_actions_menu"); + mSaveDescriptionChanges = getChild("save_description_changes"); + mDiscardDescriptionChanges = getChild("discard_description_changes"); + mCanSeeOnlineIcon = getChild("can_see_online"); + mCantSeeOnlineIcon = getChild("cant_see_online"); + mCanSeeOnMapIcon = getChild("can_see_on_map"); + mCantSeeOnMapIcon = getChild("cant_see_on_map"); + mCanEditObjectsIcon = getChild("can_edit_objects"); + mCantEditObjectsIcon = getChild("cant_edit_objects"); + + mShowInSearchCombo->setCommitCallback([this](LLUICtrl*, void*) { onShowInSearchCallback(); }, nullptr); + mHideAgeCombo->setCommitCallback([this](LLUICtrl*, void*) { onHideAgeCallback(); }, nullptr); + mGroupList->setDoubleClickCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { LLPanelProfileSecondLife::openGroupProfile(); }); + mGroupList->setReturnCallback([this](LLUICtrl*, const LLSD&) { LLPanelProfileSecondLife::openGroupProfile(); }); + mSaveDescriptionChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveDescriptionChanges(); }, nullptr); + mDiscardDescriptionChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardDescriptionChanges(); }, nullptr); + mDescriptionEdit->setKeystrokeCallback([this](LLTextEditor* caller) { onSetDescriptionDirty(); }); + + mCanSeeOnlineIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mCantSeeOnlineIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mCanSeeOnMapIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mCantSeeOnMapIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mCanEditObjectsIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mCantEditObjectsIcon->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentPermissionsDialog(); }); + mSecondLifePic->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask) { onShowAgentProfileTexture(); }); + + return true; +} + +void LLPanelProfileSecondLife::onOpen(const LLSD& key) +{ + LLPanelProfileTab::onOpen(key); + + resetData(); + + LLUUID avatar_id = getAvatarId(); + + bool own_profile = getSelfProfile(); + + mGroupList->setShowNone(!own_profile); + + childSetVisible("notes_panel", !own_profile); + childSetVisible("settings_panel", own_profile); + childSetVisible("about_buttons_panel", own_profile); + + if (own_profile) + { + // Group list control cannot toggle ForAgent loading + // Less than ideal, but viewing own profile via search is edge case + mGroupList->enableForAgent(false); + } + + // Init menu, menu needs to be created in scope of a registar to work correctly. + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar commit; + commit.add("Profile.Commit", [this](LLUICtrl*, const LLSD& userdata) { onCommitMenu(userdata); }); + + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable; + enable.add("Profile.EnableItem", [this](LLUICtrl*, const LLSD& userdata) { return onEnableMenu(userdata); }); + enable.add("Profile.CheckItem", [this](LLUICtrl*, const LLSD& userdata) { return onCheckMenu(userdata); }); + + if (own_profile) + { + mAgentActionMenuButton->setMenu("menu_profile_self.xml", LLMenuButton::MP_BOTTOM_RIGHT); + } + else + { + // Todo: use PeopleContextMenu instead? + mAgentActionMenuButton->setMenu("menu_profile_other.xml", LLMenuButton::MP_BOTTOM_RIGHT); + } + + mDescriptionEdit->setParseHTML(!own_profile); + + if (!own_profile) + { + mVoiceStatus = LLAvatarActions::canCall() && (LLAvatarActions::isFriend(avatar_id) ? LLAvatarTracker::instance().isBuddyOnline(avatar_id) : true); + updateOnlineStatus(); + fillRightsData(); + } + + mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2)); +} + + +bool LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + // Try children first + if (LLPanelProfileTab::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) + && *accept != ACCEPT_NO) + { + return true; + } + + // No point sharing with own profile + if (getSelfProfile()) + { + return false; + } + + // Exclude fields that look like they are editable. + S32 child_x = 0; + S32 child_y = 0; + if (localPointToOtherView(x, y, &child_x, &child_y, mDescriptionEdit) + && mDescriptionEdit->pointInView(child_x, child_y)) + { + return false; + } + + if (localPointToOtherView(x, y, &child_x, &child_y, mGroupList) + && mGroupList->pointInView(child_x, child_y)) + { + return false; + } + + // Share + LLToolDragAndDrop::handleGiveDragAndDrop(getAvatarId(), + LLUUID::null, + drop, + cargo_type, + cargo_data, + accept); + return true; +} + +void LLPanelProfileSecondLife::refreshName() +{ + if (!mAvatarNameCacheConnection.connected()) + { + mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2)); + } +} + +void LLPanelProfileSecondLife::resetData() +{ + resetLoading(); + + // Set default image and 1:1 dimensions for it + mSecondLifePic->setValue("Generic_Person_Large"); + + LLRect imageRect = mSecondLifePicLayout->getRect(); + mSecondLifePicLayout->reshape(imageRect.getWidth(), imageRect.getWidth()); + + setDescriptionText(LLStringUtil::null); + mGroups.clear(); + mGroupList->setGroups(mGroups); + + bool own_profile = getSelfProfile(); + mCanSeeOnlineIcon->setVisible(false); + mCantSeeOnlineIcon->setVisible(!own_profile); + mCanSeeOnMapIcon->setVisible(false); + mCantSeeOnMapIcon->setVisible(!own_profile); + mCanEditObjectsIcon->setVisible(false); + mCantEditObjectsIcon->setVisible(!own_profile); + + mCanSeeOnlineIcon->setEnabled(false); + mCantSeeOnlineIcon->setEnabled(false); + mCanSeeOnMapIcon->setEnabled(false); + mCantSeeOnMapIcon->setEnabled(false); + mCanEditObjectsIcon->setEnabled(false); + mCantEditObjectsIcon->setEnabled(false); + + childSetVisible("partner_layout", false); + childSetVisible("badge_layout", false); + childSetVisible("partner_spacer_layout", true); +} + +void LLPanelProfileSecondLife::processProperties(void* data, EAvatarProcessorType type) +{ + if (APT_PROPERTIES == type) + { + LLAvatarData* avatar_data = static_cast(data); + if (avatar_data && getAvatarId() == avatar_data->avatar_id) + { + processProfileProperties(avatar_data); + } + } +} + +void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avatar_data) +{ + const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); + if ((relationship != NULL || gAgent.isGodlike()) && !getSelfProfile()) + { + // Relies onto friend observer to get information about online status updates. + // Once SL-17506 gets implemented, condition might need to become: + // (gAgent.isGodlike() || isRightGrantedFrom || flags & AVATAR_ONLINE) + processOnlineStatus(relationship != NULL, + gAgent.isGodlike() || relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS), + (avatar_data->flags & AVATAR_ONLINE)); + } + + fillCommonData(avatar_data); + + fillPartnerData(avatar_data); + + fillAccountStatus(avatar_data); + + LLAvatarData::group_list_t::const_iterator it = avatar_data->group_list.begin(); + const LLAvatarData::group_list_t::const_iterator it_end = avatar_data->group_list.end(); + + for (; it_end != it; ++it) + { + LLAvatarData::LLGroupData group_data = *it; + mGroups[group_data.group_name] = group_data.group_id; + } + + mGroupList->setGroups(mGroups); + + setLoaded(); +} + +void LLPanelProfileSecondLife::openGroupProfile() +{ + LLUUID group_id = mGroupList->getSelectedUUID(); + LLGroupActions::show(group_id); +} + +void LLPanelProfileSecondLife::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) +{ + mAvatarNameCacheConnection.disconnect(); + getChild("display_name")->setValue(av_name.getDisplayName()); + getChild("user_name")->setValue(av_name.getAccountName()); +} + +void LLPanelProfileSecondLife::setProfileImageUploading(bool loading) +{ + LLLoadingIndicator* indicator = getChild("image_upload_indicator"); + indicator->setVisible(loading); + if (loading) + { + indicator->start(); + } + else + { + indicator->stop(); + } + mWaitingForImageUpload = loading; +} + +void LLPanelProfileSecondLife::setProfileImageUploaded(const LLUUID &image_asset_id) +{ + mSecondLifePic->setValue(image_asset_id); + + LLFloater *floater = mFloaterProfileTextureHandle.get(); + if (floater) + { + LLFloaterProfileTexture * texture_view = dynamic_cast(floater); + texture_view->loadAsset(mSecondLifePic->getImageAssetId()); + } + + setProfileImageUploading(false); +} + +bool LLPanelProfileSecondLife::hasUnsavedChanges() +{ + LLFloater *floater = mFloaterPermissionsHandle.get(); + if (floater) + { + LLFloaterProfilePermissions* perm = dynamic_cast(floater); + if (perm && perm->hasUnsavedChanges()) + { + return true; + } + } + // if floater + return mHasUnsavedDescriptionChanges; +} + +void LLPanelProfileSecondLife::commitUnsavedChanges() +{ + LLFloater *floater = mFloaterPermissionsHandle.get(); + if (floater) + { + LLFloaterProfilePermissions* perm = dynamic_cast(floater); + if (perm && perm->hasUnsavedChanges()) + { + perm->onApplyRights(); + } + } + if (mHasUnsavedDescriptionChanges) + { + onSaveDescriptionChanges(); + } +} + +void LLPanelProfileSecondLife::fillCommonData(const LLAvatarData* avatar_data) +{ + // Refresh avatar id in cache with new info to prevent re-requests + // and to make sure icons in text will be up to date + LLAvatarIconIDCache::getInstance()->add(avatar_data->avatar_id, avatar_data->image_id); + + fillAgeData(avatar_data); + + setDescriptionText(avatar_data->about_text); + + mSecondLifePic->setValue(avatar_data->image_id); + + if (getSelfProfile()) + { + mAllowPublish = avatar_data->flags & AVATAR_ALLOW_PUBLISH; + mShowInSearchCombo->setValue(mAllowPublish); + } +} + +void LLPanelProfileSecondLife::fillPartnerData(const LLAvatarData* avatar_data) +{ + LLTextBox* partner_text_ctrl = getChild("partner_link"); + if (avatar_data->partner_id.notNull()) + { + childSetVisible("partner_layout", true); + LLStringUtil::format_map_t args; + args["[LINK]"] = LLSLURL("agent", avatar_data->partner_id, "inspect").getSLURLString(); + std::string partner_text = getString("partner_text", args); + partner_text_ctrl->setText(partner_text); + } + else + { + childSetVisible("partner_layout", false); + } +} + +void LLPanelProfileSecondLife::fillAccountStatus(const LLAvatarData* avatar_data) +{ + LLStringUtil::format_map_t args; + args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(avatar_data); + args["[PAYMENTINFO]"] = LLAvatarPropertiesProcessor::paymentInfo(avatar_data); + + std::string caption_text = getString("CaptionTextAcctInfo", args); + getChild("account_info")->setValue(caption_text); + + const S32 LINDEN_EMPLOYEE_INDEX = 3; + LLDate sl_release; + sl_release.fromYMDHMS(2003, 6, 23, 0, 0, 0); + std::string customer_lower = avatar_data->customer_type; + LLStringUtil::toLower(customer_lower); + if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX) + { + getChild("badge_icon")->setValue("Profile_Badge_Linden"); + getChild("badge_text")->setValue(getString("BadgeLinden")); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); + } + else if (avatar_data->born_on < sl_release) + { + getChild("badge_icon")->setValue("Profile_Badge_Beta"); + getChild("badge_text")->setValue(getString("BadgeBeta")); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); + } + else if (customer_lower == "beta_lifetime") + { + getChild("badge_icon")->setValue("Profile_Badge_Beta_Lifetime"); + getChild("badge_text")->setValue(getString("BadgeBetaLifetime")); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); + } + else if (customer_lower == "lifetime") + { + getChild("badge_icon")->setValue("Profile_Badge_Lifetime"); + getChild("badge_text")->setValue(getString("BadgeLifetime")); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); + } + else if (customer_lower == "secondlifetime_premium") + { + getChild("badge_icon")->setValue("Profile_Badge_Premium_Lifetime"); + getChild("badge_text")->setValue(getString("BadgePremiumLifetime")); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); + } + else if (customer_lower == "secondlifetime_premium_plus") + { + getChild("badge_icon")->setValue("Profile_Badge_Pplus_Lifetime"); + getChild("badge_text")->setValue(getString("BadgePremiumPlusLifetime")); + childSetVisible("badge_layout", true); + childSetVisible("partner_spacer_layout", false); + } + else + { + childSetVisible("badge_layout", false); + childSetVisible("partner_spacer_layout", true); + } +} + +void LLPanelProfileSecondLife::fillRightsData() +{ + if (getSelfProfile()) + { + return; + } + + 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(); + bool can_see_online = LLRelationship::GRANT_ONLINE_STATUS & rights; + bool can_see_on_map = LLRelationship::GRANT_MAP_LOCATION & rights; + bool can_edit_objects = LLRelationship::GRANT_MODIFY_OBJECTS & rights; + + mCanSeeOnlineIcon->setVisible(can_see_online); + mCantSeeOnlineIcon->setVisible(!can_see_online); + mCanSeeOnMapIcon->setVisible(can_see_on_map); + mCantSeeOnMapIcon->setVisible(!can_see_on_map); + mCanEditObjectsIcon->setVisible(can_edit_objects); + mCantEditObjectsIcon->setVisible(!can_edit_objects); + + mCanSeeOnlineIcon->setEnabled(true); + mCantSeeOnlineIcon->setEnabled(true); + mCanSeeOnMapIcon->setEnabled(true); + mCantSeeOnMapIcon->setEnabled(true); + mCanEditObjectsIcon->setEnabled(true); + mCantEditObjectsIcon->setEnabled(true); + } + else + { + mCanSeeOnlineIcon->setVisible(false); + mCantSeeOnlineIcon->setVisible(false); + mCanSeeOnMapIcon->setVisible(false); + mCantSeeOnMapIcon->setVisible(false); + mCanEditObjectsIcon->setVisible(false); + mCantEditObjectsIcon->setVisible(false); + } +} + +void LLPanelProfileSecondLife::fillAgeData(const LLAvatarData* avatar_data) +{ + // Date from server comes already converted to stl timezone, + // so display it as an UTC + 0 + bool hide_age = avatar_data->hide_age && !getSelfProfile(); + std::string name_and_date = getString(hide_age ? "date_format_short" : "date_format_full"); + LLSD args_name; + args_name["datetime"] = (S32)avatar_data->born_on.secondsSinceEpoch(); + LLStringUtil::format(name_and_date, args_name); + getChild("sl_birth_date")->setValue(name_and_date); + + LLUICtrl* userAgeCtrl = getChild("user_age"); + if (hide_age) + { + userAgeCtrl->setVisible(false); + } + else + { + std::string register_date = getString("age_format"); + LLSD args_age; + args_age["[AGE]"] = LLDateUtil::ageFromDate(avatar_data->born_on, LLDate::now()); + LLStringUtil::format(register_date, args_age); + userAgeCtrl->setValue(register_date); + } + + bool showHideAgeCombo = false; + if (getSelfProfile()) + { + if (LLAvatarPropertiesProcessor::getInstance()->isHideAgeSupportedByServer()) + { + F64 birth = avatar_data->born_on.secondsSinceEpoch(); + F64 now = LLDate::now().secondsSinceEpoch(); + if (now - birth > 365 * 24 * 60 * 60) + { + mHideAge = avatar_data->hide_age; + mHideAgeCombo->setValue(mHideAge); + showHideAgeCombo = true; + } + } + } + mHideAgeCombo->setVisible(showHideAgeCombo); +} + +void LLPanelProfileSecondLife::onImageLoaded(bool success, LLViewerFetchedTexture *imagep) +{ + LLRect imageRect = mSecondLifePicLayout->getRect(); + if (!success || imagep->getFullWidth() == imagep->getFullHeight()) + { + mSecondLifePicLayout->reshape(imageRect.getWidth(), imageRect.getWidth()); + } + else + { + // assume 3:4, for sake of firestorm + mSecondLifePicLayout->reshape(imageRect.getWidth(), imageRect.getWidth() * 3 / 4); + } +} + +// virtual, called by LLAvatarTracker +void LLPanelProfileSecondLife::changed(U32 mask) +{ + updateOnlineStatus(); + if (mask != LLFriendObserver::ONLINE) + { + fillRightsData(); + } +} + +// virtual, called by LLVoiceClient +void LLPanelProfileSecondLife::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ + 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); + } + + LLPanelProfilePropertiesProcessorTab::setAvatarId(avatar_id); + + if (LLAvatarActions::isFriend(getAvatarId())) + { + LLAvatarTracker::instance().addParticularFriendObserver(getAvatarId(), this); + } + } +} + +// method was disabled according to EXT-2022. Re-enabled & improved according to EXT-3880 +void LLPanelProfileSecondLife::updateOnlineStatus() +{ + const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); + if (relationship != NULL) + { + // For friend let check if he allowed me to see his status + bool online = relationship->isOnline(); + bool perm_granted = relationship->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS); + processOnlineStatus(true, perm_granted, online); + } + else + { + childSetVisible("friend_layout", false); + childSetVisible("online_layout", false); + childSetVisible("offline_layout", false); + } +} + +void LLPanelProfileSecondLife::processOnlineStatus(bool is_friend, bool show_online, bool online) +{ + childSetVisible("friend_layout", is_friend); + childSetVisible("online_layout", online && show_online); + childSetVisible("offline_layout", !online && show_online); +} + +void LLPanelProfileSecondLife::setLoaded() +{ + LLPanelProfileTab::setLoaded(); + + if (getSelfProfile()) + { + mShowInSearchCombo->setEnabled(true); + if (mHideAgeCombo->getVisible()) + { + mHideAgeCombo->setEnabled(true); + } + mDescriptionEdit->setEnabled(true); + } +} + + +class LLProfileImagePicker : public LLFilePickerThread +{ +public: + LLProfileImagePicker(EProfileImageType type, LLHandle *handle); + ~LLProfileImagePicker(); + void notify(const std::vector& filenames) override; + +private: + LLHandle *mHandle; + EProfileImageType mType; +}; + +LLProfileImagePicker::LLProfileImagePicker(EProfileImageType type, LLHandle *handle) + : LLFilePickerThread(LLFilePicker::FFLOAD_IMAGE), + mHandle(handle), + mType(type) +{ +} + +LLProfileImagePicker::~LLProfileImagePicker() +{ + delete mHandle; +} + +void LLProfileImagePicker::notify(const std::vector& filenames) +{ + if (mHandle->isDead()) + { + return; + } + if (filenames.empty()) + { + return; + } + std::string file_path = filenames[0]; + if (file_path.empty()) + { + return; + } + + // generate a temp texture file for coroutine + std::string temp_file = gDirUtilp->getTempFilename(); + U32 codec = LLImageBase::getCodecFromExtension(gDirUtilp->getExtension(file_path)); + const S32 MAX_DIM = 256; + if (!LLViewerTextureList::createUploadFile(file_path, temp_file, codec, MAX_DIM)) + { + LLSD notif_args; + notif_args["REASON"] = LLImage::getLastThreadError().c_str(); + LLNotificationsUtil::add("CannotUploadTexture", notif_args); + LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)mType << ", " << notif_args["REASON"].asString() << LL_ENDL; + return; + } + + std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP); + if (cap_url.empty()) + { + LLSD args; + args["CAPABILITY"] = PROFILE_IMAGE_UPLOAD_CAP; + LLNotificationsUtil::add("RegionCapabilityRequestError", args); + LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)mType << ", no cap found" << LL_ENDL; + return; + } + + switch (mType) + { + case PROFILE_IMAGE_SL: + { + LLPanelProfileSecondLife* panel = static_cast(mHandle->get()); + panel->setProfileImageUploading(true); + } + break; + case PROFILE_IMAGE_FL: + { + LLPanelProfileFirstLife* panel = static_cast(mHandle->get()); + panel->setProfileImageUploading(true); + } + break; + } + + LLCoros::instance().launch("postAgentUserImageCoro", + boost::bind(post_profile_image_coro, cap_url, mType, temp_file, mHandle)); + + mHandle = nullptr; // transferred to post_profile_image_coro +} + +void LLPanelProfileSecondLife::onCommitMenu(const LLSD& userdata) +{ + const std::string item_name = userdata.asString(); + const LLUUID agent_id = getAvatarId(); + // todo: consider moving this into LLAvatarActions::onCommit(name, id) + // and making all other flaoters, like people menu do the same + if (item_name == "im") + { + LLAvatarActions::startIM(agent_id); + } + else if (item_name == "offer_teleport") + { + LLAvatarActions::offerTeleport(agent_id); + } + else if (item_name == "request_teleport") + { + LLAvatarActions::teleportRequest(agent_id); + } + else if (item_name == "voice_call") + { + LLAvatarActions::startCall(agent_id); + } + else if (item_name == "chat_history") + { + LLAvatarActions::viewChatHistory(agent_id); + } + else if (item_name == "add_friend") + { + LLAvatarActions::requestFriendshipDialog(agent_id); + } + else if (item_name == "remove_friend") + { + LLAvatarActions::removeFriendDialog(agent_id); + } + else if (item_name == "invite_to_group") + { + LLAvatarActions::inviteToGroup(agent_id); + } + else if (item_name == "can_show_on_map") + { + LLAvatarActions::showOnMap(agent_id); + } + else if (item_name == "share") + { + LLAvatarActions::share(agent_id); + } + else if (item_name == "pay") + { + LLAvatarActions::pay(agent_id); + } + else if (item_name == "toggle_block_agent") + { + LLAvatarActions::toggleBlock(agent_id); + } + else if (item_name == "copy_user_id") + { + LLWString wstr = utf8str_to_wstring(getAvatarId().asString()); + LLClipboard::instance().copyToClipboard(wstr, 0, wstr.size()); + } + else if (item_name == "agent_permissions") + { + onShowAgentPermissionsDialog(); + } + else if (item_name == "copy_display_name" + || item_name == "copy_username") + { + LLAvatarName av_name; + if (!LLAvatarNameCache::get(getAvatarId(), &av_name)) + { + // shouldn't happen, option is supposed to be invisible while name is fetching + LL_WARNS() << "Failed to get agent data" << LL_ENDL; + return; + } + LLWString wstr; + if (item_name == "copy_display_name") + { + wstr = utf8str_to_wstring(av_name.getDisplayName(true)); + } + else if (item_name == "copy_username") + { + wstr = utf8str_to_wstring(av_name.getUserName()); + } + LLClipboard::instance().copyToClipboard(wstr, 0, wstr.size()); + } + else if (item_name == "edit_display_name") + { + LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCacheSetName, this, _1, _2)); + LLFirstUse::setDisplayName(false); + } + else if (item_name == "edit_partner") + { + std::string url = "https://[GRID]/my/account/partners.php"; + LLSD subs; + url = LLWeb::expandURLSubstitutions(url, subs); + LLUrlAction::openURL(url); + } + else if (item_name == "upload_photo") + { + (new LLProfileImagePicker(PROFILE_IMAGE_SL, new LLHandle(LLPanel::getHandle())))->getFile(); + + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + if (floaterp) + { + floaterp->closeFloater(); + } + } + else if (item_name == "change_photo") + { + onShowTexturePicker(); + } + else if (item_name == "remove_photo") + { + onCommitProfileImage(LLUUID::null); + + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + if (floaterp) + { + floaterp->closeFloater(); + } + } +} + +bool LLPanelProfileSecondLife::onEnableMenu(const LLSD& userdata) +{ + const std::string item_name = userdata.asString(); + const LLUUID agent_id = getAvatarId(); + if (item_name == "offer_teleport" || item_name == "request_teleport") + { + return LLAvatarActions::canOfferTeleport(agent_id); + } + else if (item_name == "voice_call") + { + return mVoiceStatus; + } + else if (item_name == "chat_history") + { + return LLLogChat::isTranscriptExist(agent_id); + } + else if (item_name == "add_friend") + { + return !LLAvatarActions::isFriend(agent_id); + } + else if (item_name == "remove_friend") + { + return LLAvatarActions::isFriend(agent_id); + } + else if (item_name == "can_show_on_map") + { + return (LLAvatarTracker::instance().isBuddyOnline(agent_id) && is_agent_mappable(agent_id)) + || gAgent.isGodlike(); + } + else if (item_name == "toggle_block_agent") + { + return LLAvatarActions::canBlock(agent_id); + } + else if (item_name == "agent_permissions") + { + return LLAvatarActions::isFriend(agent_id); + } + else if (item_name == "copy_display_name" + || item_name == "copy_username") + { + return !mAvatarNameCacheConnection.connected(); + } + else if (item_name == "upload_photo" + || item_name == "change_photo") + { + std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP); + return !cap_url.empty() && !mWaitingForImageUpload && getIsLoaded(); + } + else if (item_name == "remove_photo") + { + std::string cap_url = gAgent.getRegionCapability(PROFILE_PROPERTIES_CAP); + return mSecondLifePic->getImageAssetId().notNull() && !cap_url.empty() && !mWaitingForImageUpload && getIsLoaded(); + } + + return false; +} + +bool LLPanelProfileSecondLife::onCheckMenu(const LLSD& userdata) +{ + const std::string item_name = userdata.asString(); + const LLUUID agent_id = getAvatarId(); + if (item_name == "toggle_block_agent") + { + return LLAvatarActions::isBlocked(agent_id); + } + return 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"); +} + +void LLPanelProfileSecondLife::setDescriptionText(const std::string &text) +{ + mSaveDescriptionChanges->setEnabled(false); + mDiscardDescriptionChanges->setEnabled(false); + mHasUnsavedDescriptionChanges = false; + + mDescriptionText = text; + mDescriptionEdit->setValue(mDescriptionText); +} + +void LLPanelProfileSecondLife::onSetDescriptionDirty() +{ + mSaveDescriptionChanges->setEnabled(true); + mDiscardDescriptionChanges->setEnabled(true); + mHasUnsavedDescriptionChanges = true; +} + +void LLPanelProfileSecondLife::onShowInSearchCallback() +{ + bool value = mShowInSearchCombo->getValue().asInteger(); + if (value == mAllowPublish) + return; + + mAllowPublish = value; + saveAgentUserInfoCoro("allow_publish", value); +} + +void LLPanelProfileSecondLife::onHideAgeCallback() +{ + bool value = mHideAgeCombo->getValue().asInteger(); + if (value == mHideAge) + return; + + mHideAge = value; + saveAgentUserInfoCoro("hide_age", value); +} + +void LLPanelProfileSecondLife::onSaveDescriptionChanges() +{ + mDescriptionText = mDescriptionEdit->getValue().asString(); + saveAgentUserInfoCoro("sl_about_text", mDescriptionText); + + mSaveDescriptionChanges->setEnabled(false); + mDiscardDescriptionChanges->setEnabled(false); + mHasUnsavedDescriptionChanges = false; +} + +void LLPanelProfileSecondLife::onDiscardDescriptionChanges() +{ + setDescriptionText(mDescriptionText); +} + +void LLPanelProfileSecondLife::onShowAgentPermissionsDialog() +{ + LLFloater *floater = mFloaterPermissionsHandle.get(); + if (!floater) + { + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + if (parent_floater) + { + LLFloaterProfilePermissions * perms = new LLFloaterProfilePermissions(parent_floater, getAvatarId()); + mFloaterPermissionsHandle = perms->getHandle(); + perms->openFloater(); + perms->setVisibleAndFrontmost(true); + + parent_floater->addDependentFloater(mFloaterPermissionsHandle); + } + } + else // already open + { + floater->setMinimized(false); + floater->setVisibleAndFrontmost(true); + } +} + +void LLPanelProfileSecondLife::onShowAgentProfileTexture() +{ + if (!getIsLoaded()) + { + return; + } + + LLFloater *floater = mFloaterProfileTextureHandle.get(); + if (!floater) + { + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + if (parent_floater) + { + LLFloaterProfileTexture * texture_view = new LLFloaterProfileTexture(parent_floater); + mFloaterProfileTextureHandle = texture_view->getHandle(); + if (mSecondLifePic->getImageAssetId().notNull()) + { + texture_view->loadAsset(mSecondLifePic->getImageAssetId()); + } + else + { + texture_view->resetAsset(); + } + texture_view->openFloater(); + texture_view->setVisibleAndFrontmost(true); + + parent_floater->addDependentFloater(mFloaterProfileTextureHandle); + } + } + else // already open + { + LLFloaterProfileTexture * texture_view = dynamic_cast(floater); + texture_view->setMinimized(false); + texture_view->setVisibleAndFrontmost(true); + if (mSecondLifePic->getImageAssetId().notNull()) + { + texture_view->loadAsset(mSecondLifePic->getImageAssetId()); + } + else + { + texture_view->resetAsset(); + } + } +} + +void LLPanelProfileSecondLife::onShowTexturePicker() +{ + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + + // Show the dialog + if (!floaterp) + { + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + if (parent_floater) + { + // because inventory construction is somewhat slow + getWindow()->setCursor(UI_CURSOR_WAIT); + LLFloaterTexturePicker* texture_floaterp = new LLFloaterTexturePicker( + this, + mSecondLifePic->getImageAssetId(), + LLUUID::null, + mSecondLifePic->getImageAssetId(), + false, + false, + "SELECT PHOTO", + PERM_NONE, + PERM_NONE, + false, + NULL, + PICK_TEXTURE); + + mFloaterTexturePickerHandle = texture_floaterp->getHandle(); + + texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID&, const LLUUID&) + { + if (op == LLTextureCtrl::TEXTURE_SELECT) + { + onCommitProfileImage(asset_id); + } + }); + texture_floaterp->setLocalTextureEnabled(false); + texture_floaterp->setBakeTextureEnabled(false); + texture_floaterp->setCanApply(false, true, false); + + parent_floater->addDependentFloater(mFloaterTexturePickerHandle); + + texture_floaterp->openFloater(); + texture_floaterp->setFocus(true); + } + } + else + { + floaterp->setMinimized(false); + floaterp->setVisibleAndFrontmost(true); + } +} + +void LLPanelProfileSecondLife::onCommitProfileImage(const LLUUID& id) +{ + if (mSecondLifePic->getImageAssetId() == id) + return; + + std::function callback = [id](bool result) + { + if (result) + { + LLAvatarIconIDCache::getInstance()->add(gAgentID, id); + // Should trigger callbacks in icon controls (or request Legacy) + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(gAgentID); + } + }; + + if (!saveAgentUserInfoCoro("sl_image_id", id, callback)) + return; + + mSecondLifePic->setValue(id); + + LLFloater *floater = mFloaterProfileTextureHandle.get(); + if (floater) + { + LLFloaterProfileTexture * texture_view = dynamic_cast(floater); + if (id == LLUUID::null) + { + texture_view->resetAsset(); + } + else + { + texture_view->loadAsset(id); + } + } +} + +////////////////////////////////////////////////////////////////////////// +// 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() +{ + mWebBrowser = getChild("profile_html"); + mWebBrowser->addObserver(this); + mWebBrowser->setHomePageUrl("about:blank"); + + return true; +} + +void LLPanelProfileWeb::resetData() +{ + mWebBrowser->navigateHome(); +} + +void LLPanelProfileWeb::updateData() +{ + LLUUID avatar_id = getAvatarId(); + if (!getStarted() && avatar_id.notNull() && !mURLWebProfile.empty()) + { + setIsLoading(); + + 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, true); + if (mURLWebProfile.empty()) + { + return; + } + + //if the tab was opened before name was resolved, load the panel now + 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::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) +{ + switch(event) + { + case MEDIA_EVENT_STATUS_TEXT_CHANGED: + childSetValue("status_text", LLSD( self->getStatusText() ) ); + 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)) ); + + setLoaded(); + } + break; + + default: + // Having a default case makes the compiler happy. + break; + } +} + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLPanelProfileFirstLife::LLPanelProfileFirstLife() + : LLPanelProfilePropertiesProcessorTab() + , mHasUnsavedChanges(false) +{ +} + +LLPanelProfileFirstLife::~LLPanelProfileFirstLife() +{ +} + +bool LLPanelProfileFirstLife::postBuild() +{ + mDescriptionEdit = getChild("fl_description_edit"); + mPicture = getChild("real_world_pic"); + + mUploadPhoto = getChild("fl_upload_image"); + mChangePhoto = getChild("fl_change_image"); + mRemovePhoto = getChild("fl_remove_image"); + mSaveChanges = getChild("fl_save_changes"); + mDiscardChanges = getChild("fl_discard_changes"); + + mUploadPhoto->setCommitCallback([this](LLUICtrl*, void*) { onUploadPhoto(); }, nullptr); + mChangePhoto->setCommitCallback([this](LLUICtrl*, void*) { onChangePhoto(); }, nullptr); + mRemovePhoto->setCommitCallback([this](LLUICtrl*, void*) { onRemovePhoto(); }, nullptr); + mSaveChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveDescriptionChanges(); }, nullptr); + mDiscardChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardDescriptionChanges(); }, nullptr); + mDescriptionEdit->setKeystrokeCallback([this](LLTextEditor* caller) { onSetDescriptionDirty(); }); + + return true; +} + +void LLPanelProfileFirstLife::onOpen(const LLSD& key) +{ + LLPanelProfileTab::onOpen(key); + + if (!getSelfProfile()) + { + // Otherwise as the only focusable element it will be selected + mDescriptionEdit->setTabStop(false); + } + + resetData(); +} + +void LLPanelProfileFirstLife::setProfileImageUploading(bool loading) +{ + mUploadPhoto->setEnabled(!loading); + mChangePhoto->setEnabled(!loading); + mRemovePhoto->setEnabled(!loading && mPicture->getImageAssetId().notNull()); + + LLLoadingIndicator* indicator = getChild("image_upload_indicator"); + indicator->setVisible(loading); + if (loading) + { + indicator->start(); + } + else + { + indicator->stop(); + } +} + +void LLPanelProfileFirstLife::setProfileImageUploaded(const LLUUID &image_asset_id) +{ + mPicture->setValue(image_asset_id); + setProfileImageUploading(false); +} + +void LLPanelProfileFirstLife::commitUnsavedChanges() +{ + if (mHasUnsavedChanges) + { + onSaveDescriptionChanges(); + } +} + +void LLPanelProfileFirstLife::onUploadPhoto() +{ + (new LLProfileImagePicker(PROFILE_IMAGE_FL, new LLHandle(LLPanel::getHandle())))->getFile(); + + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + if (floaterp) + { + floaterp->closeFloater(); + } +} + +void LLPanelProfileFirstLife::onChangePhoto() +{ + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + + // Show the dialog + if (!floaterp) + { + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + if (parent_floater) + { + // because inventory construction is somewhat slow + getWindow()->setCursor(UI_CURSOR_WAIT); + LLFloaterTexturePicker* texture_floaterp = new LLFloaterTexturePicker( + this, + mPicture->getImageAssetId(), + LLUUID::null, + mPicture->getImageAssetId(), + false, + false, + "SELECT PHOTO", + PERM_NONE, + PERM_NONE, + false, + NULL, + PICK_TEXTURE); + + mFloaterTexturePickerHandle = texture_floaterp->getHandle(); + + texture_floaterp->setOnFloaterCommitCallback([this](LLTextureCtrl::ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID&, const LLUUID&) + { + if (op == LLTextureCtrl::TEXTURE_SELECT) + { + onCommitPhoto(asset_id); + } + }); + texture_floaterp->setLocalTextureEnabled(false); + texture_floaterp->setCanApply(false, true, false); + + parent_floater->addDependentFloater(mFloaterTexturePickerHandle); + + texture_floaterp->openFloater(); + texture_floaterp->setFocus(true); + } + } + else + { + floaterp->setMinimized(false); + floaterp->setVisibleAndFrontmost(true); + } +} + +void LLPanelProfileFirstLife::onRemovePhoto() +{ + onCommitPhoto(LLUUID::null); + + LLFloater* floaterp = mFloaterTexturePickerHandle.get(); + if (floaterp) + { + floaterp->closeFloater(); + } +} + +void LLPanelProfileFirstLife::onCommitPhoto(const LLUUID& id) +{ + if (mPicture->getImageAssetId() == id) + return; + + if (!saveAgentUserInfoCoro("fl_image_id", id)) + return; + + mPicture->setValue(id); + + mRemovePhoto->setEnabled(id.notNull()); +} + +void LLPanelProfileFirstLife::setDescriptionText(const std::string &text) +{ + mSaveChanges->setEnabled(false); + mDiscardChanges->setEnabled(false); + mHasUnsavedChanges = false; + + mCurrentDescription = text; + mDescriptionEdit->setValue(mCurrentDescription); +} + +void LLPanelProfileFirstLife::onSetDescriptionDirty() +{ + mSaveChanges->setEnabled(true); + mDiscardChanges->setEnabled(true); + mHasUnsavedChanges = true; +} + +void LLPanelProfileFirstLife::onSaveDescriptionChanges() +{ + mCurrentDescription = mDescriptionEdit->getValue().asString(); + saveAgentUserInfoCoro("fl_about_text", mCurrentDescription); + + mSaveChanges->setEnabled(false); + mDiscardChanges->setEnabled(false); + mHasUnsavedChanges = false; +} + +void LLPanelProfileFirstLife::onDiscardDescriptionChanges() +{ + setDescriptionText(mCurrentDescription); +} + +void LLPanelProfileFirstLife::processProperties(void* data, EAvatarProcessorType type) +{ + if (APT_PROPERTIES == type) + { + LLAvatarData* avatar_data = static_cast(data); + if (avatar_data && getAvatarId() == avatar_data->avatar_id) + { + processProperties(avatar_data); + } + } +} + +void LLPanelProfileFirstLife::processProperties(const LLAvatarData* avatar_data) +{ + setDescriptionText(avatar_data->fl_about_text); + + mPicture->setValue(avatar_data->fl_image_id); + + setLoaded(); +} + +void LLPanelProfileFirstLife::resetData() +{ + setDescriptionText(std::string()); + mPicture->setValue(LLUUID::null); + + mUploadPhoto->setVisible(getSelfProfile()); + mChangePhoto->setVisible(getSelfProfile()); + mRemovePhoto->setVisible(getSelfProfile()); + mSaveChanges->setVisible(getSelfProfile()); + mDiscardChanges->setVisible(getSelfProfile()); +} + +void LLPanelProfileFirstLife::setLoaded() +{ + LLPanelProfileTab::setLoaded(); + + if (getSelfProfile()) + { + mDescriptionEdit->setEnabled(true); + mPicture->setEnabled(true); + mRemovePhoto->setEnabled(mPicture->getImageAssetId().notNull()); + } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLPanelProfileNotes::LLPanelProfileNotes() +: LLPanelProfilePropertiesProcessorTab() + , mHasUnsavedChanges(false) +{ + +} + +LLPanelProfileNotes::~LLPanelProfileNotes() +{ +} + +void LLPanelProfileNotes::commitUnsavedChanges() +{ + if (mHasUnsavedChanges) + { + onSaveNotesChanges(); + } +} + +bool LLPanelProfileNotes::postBuild() +{ + mNotesEditor = getChild("notes_edit"); + mSaveChanges = getChild("notes_save_changes"); + mDiscardChanges = getChild("notes_discard_changes"); + + mSaveChanges->setCommitCallback([this](LLUICtrl*, void*) { onSaveNotesChanges(); }, nullptr); + mDiscardChanges->setCommitCallback([this](LLUICtrl*, void*) { onDiscardNotesChanges(); }, nullptr); + mNotesEditor->setKeystrokeCallback([this](LLTextEditor* caller) { onSetNotesDirty(); }); + + return true; +} + +void LLPanelProfileNotes::onOpen(const LLSD& key) +{ + LLPanelProfileTab::onOpen(key); + + resetData(); +} + +void LLPanelProfileNotes::setNotesText(const std::string &text) +{ + mSaveChanges->setEnabled(false); + mDiscardChanges->setEnabled(false); + mHasUnsavedChanges = false; + + mCurrentNotes = text; + mNotesEditor->setValue(mCurrentNotes); +} + +void LLPanelProfileNotes::onSetNotesDirty() +{ + mSaveChanges->setEnabled(true); + mDiscardChanges->setEnabled(true); + mHasUnsavedChanges = true; +} + +void LLPanelProfileNotes::onSaveNotesChanges() +{ + mCurrentNotes = mNotesEditor->getValue().asString(); + saveAgentUserInfoCoro("notes", mCurrentNotes); + + mSaveChanges->setEnabled(false); + mDiscardChanges->setEnabled(false); + mHasUnsavedChanges = false; +} + +void LLPanelProfileNotes::onDiscardNotesChanges() +{ + setNotesText(mCurrentNotes); +} + +void LLPanelProfileNotes::processProperties(void* data, EAvatarProcessorType type) +{ + if (APT_PROPERTIES == type) + { + LLAvatarData* avatar_data = static_cast(data); + if (avatar_data && getAvatarId() == avatar_data->avatar_id) + { + processProperties(avatar_data); + } + } +} + +void LLPanelProfileNotes::processProperties(const LLAvatarData* avatar_data) +{ + setNotesText(avatar_data->notes); + mNotesEditor->setEnabled(true); + setLoaded(); +} + +void LLPanelProfileNotes::resetData() +{ + resetLoading(); + setNotesText(std::string()); +} + + +////////////////////////////////////////////////////////////////////////// +// LLPanelProfile + +LLPanelProfile::LLPanelProfile() + : LLPanelProfileTab() +{ +} + +LLPanelProfile::~LLPanelProfile() +{ +} + +bool LLPanelProfile::postBuild() +{ + return true; +} + +void LLPanelProfile::onTabChange() +{ + LLPanelProfileTab* active_panel = dynamic_cast(mTabContainer->getCurrentPanel()); + if (active_panel) + { + active_panel->updateData(); + } +} + +void LLPanelProfile::onOpen(const LLSD& key) +{ + LLUUID avatar_id = key["id"].asUUID(); + + // Don't reload the same profile + if (getAvatarId() == avatar_id) + { + return; + } + + LLPanelProfileTab::onOpen(avatar_id); + + mTabContainer = getChild("panel_profile_tabs"); + mPanelSecondlife = findChild(PANEL_SECONDLIFE); + mPanelWeb = findChild(PANEL_WEB); + mPanelPicks = findChild(PANEL_PICKS); + mPanelClassifieds = findChild(PANEL_CLASSIFIEDS); + mPanelFirstlife = findChild(PANEL_FIRSTLIFE); + mPanelNotes = findChild(PANEL_NOTES); + + mPanelSecondlife->onOpen(avatar_id); + mPanelWeb->onOpen(avatar_id); + mPanelPicks->onOpen(avatar_id); + mPanelClassifieds->onOpen(avatar_id); + mPanelFirstlife->onOpen(avatar_id); + mPanelNotes->onOpen(avatar_id); + + // Always request the base profile info + resetLoading(); + updateData(); + + // Some tabs only request data when opened + mTabContainer->setCommitCallback(boost::bind(&LLPanelProfile::onTabChange, this)); +} + +void LLPanelProfile::updateData() +{ + LLUUID avatar_id = getAvatarId(); + // Todo: getIsloading functionality needs to be expanded to + // include 'inited' or 'data_provided' state to not rerequest + if (!getStarted() && avatar_id.notNull()) + { + setIsLoading(); + + mPanelSecondlife->setIsLoading(); + mPanelPicks->setIsLoading(); + mPanelFirstlife->setIsLoading(); + mPanelNotes->setIsLoading(); + + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(getAvatarId()); + } +} + +void LLPanelProfile::refreshName() +{ + mPanelSecondlife->refreshName(); +} + +void LLPanelProfile::createPick(const LLPickData &data) +{ + mTabContainer->selectTabPanel(mPanelPicks); + mPanelPicks->createPick(data); +} + +void LLPanelProfile::showPick(const LLUUID& pick_id) +{ + if (pick_id.notNull()) + { + mPanelPicks->selectPick(pick_id); + } + mTabContainer->selectTabPanel(mPanelPicks); +} + +bool LLPanelProfile::isPickTabSelected() +{ + return (mTabContainer->getCurrentPanel() == mPanelPicks); +} + +bool LLPanelProfile::isNotesTabSelected() +{ + return (mTabContainer->getCurrentPanel() == mPanelNotes); +} + +bool LLPanelProfile::hasUnsavedChanges() +{ + return mPanelSecondlife->hasUnsavedChanges() + || mPanelPicks->hasUnsavedChanges() + || mPanelClassifieds->hasUnsavedChanges() + || mPanelFirstlife->hasUnsavedChanges() + || mPanelNotes->hasUnsavedChanges(); +} + +bool LLPanelProfile::hasUnpublishedClassifieds() +{ + return mPanelClassifieds->hasNewClassifieds(); +} + +void LLPanelProfile::commitUnsavedChanges() +{ + mPanelSecondlife->commitUnsavedChanges(); + mPanelPicks->commitUnsavedChanges(); + mPanelClassifieds->commitUnsavedChanges(); + mPanelFirstlife->commitUnsavedChanges(); + mPanelNotes->commitUnsavedChanges(); +} + +void LLPanelProfile::showClassified(const LLUUID& classified_id, bool edit) +{ + if (classified_id.notNull()) + { + mPanelClassifieds->selectClassified(classified_id, edit); + } + mTabContainer->selectTabPanel(mPanelClassifieds); +} + +void LLPanelProfile::createClassified() +{ + mPanelClassifieds->createClassified(); + mTabContainer->selectTabPanel(mPanelClassifieds); +} + -- cgit v1.2.3 From b42f9d836b4c0f7fbd4bdae1734021e2a09fdbe8 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sat, 1 Jun 2024 15:49:26 +0200 Subject: Re-enable a lot of compiler warnings for MSVC and address the C4267 "possible loss of precision" warnings --- indra/newview/llpanelprofile.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llpanelprofile.cpp') diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 579f0941c3..19e2d5de99 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -1430,7 +1430,7 @@ void LLPanelProfileSecondLife::onCommitMenu(const LLSD& userdata) else if (item_name == "copy_user_id") { LLWString wstr = utf8str_to_wstring(getAvatarId().asString()); - LLClipboard::instance().copyToClipboard(wstr, 0, wstr.size()); + LLClipboard::instance().copyToClipboard(wstr, 0, static_cast(wstr.size())); } else if (item_name == "agent_permissions") { @@ -1455,7 +1455,7 @@ void LLPanelProfileSecondLife::onCommitMenu(const LLSD& userdata) { wstr = utf8str_to_wstring(av_name.getUserName()); } - LLClipboard::instance().copyToClipboard(wstr, 0, wstr.size()); + LLClipboard::instance().copyToClipboard(wstr, 0, static_cast(wstr.size())); } else if (item_name == "edit_display_name") { -- cgit v1.2.3