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