summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorTofu Linden <tofu.linden@lindenlab.com>2010-01-22 10:51:58 -0800
committerTofu Linden <tofu.linden@lindenlab.com>2010-01-22 10:51:58 -0800
commit3889d4329962cc497bccbc8bbe9e6678ab3c9e6c (patch)
treeda02c07350e9c4def5013376dbbc382a3e49d57e /indra/newview
parentfa891c062ef66410123c66de1ef67b7dcef327db (diff)
parent09e9cdeb2e7e979ea1d4898fa7c2d40e8ebc52b2 (diff)
PE merge.
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/app_settings/settings.xml12
-rw-r--r--indra/newview/llcallfloater.cpp69
-rw-r--r--indra/newview/llcallfloater.h31
-rw-r--r--indra/newview/llchiclet.cpp2
-rw-r--r--indra/newview/llfavoritesbar.cpp5
-rw-r--r--indra/newview/llfloaterreporter.cpp43
-rw-r--r--indra/newview/llfloaterreporter.h4
-rw-r--r--indra/newview/llfolderview.cpp1
-rw-r--r--indra/newview/llimfloater.cpp7
-rw-r--r--indra/newview/llimfloater.h2
-rw-r--r--indra/newview/llimfloatercontainer.cpp84
-rw-r--r--indra/newview/llimfloatercontainer.h21
-rw-r--r--indra/newview/llimview.cpp69
-rw-r--r--indra/newview/llimview.h14
-rw-r--r--indra/newview/llinspectavatar.cpp2
-rw-r--r--indra/newview/llinventorybridge.cpp12
-rw-r--r--indra/newview/llinventorybridge.h1
-rw-r--r--indra/newview/lllocationinputctrl.cpp52
-rw-r--r--indra/newview/lllocationinputctrl.h23
-rw-r--r--indra/newview/lllogchat.cpp6
-rw-r--r--indra/newview/lllogchat.h2
-rw-r--r--indra/newview/llpanelgroup.cpp18
-rw-r--r--indra/newview/llpanelgrouproles.cpp41
-rw-r--r--indra/newview/llpanelgrouproles.h2
-rw-r--r--indra/newview/llpanelimcontrolpanel.cpp9
-rw-r--r--indra/newview/llpanelimcontrolpanel.h3
-rw-r--r--indra/newview/llpanelplaceinfo.cpp27
-rw-r--r--indra/newview/llpanelplaceinfo.h1
-rw-r--r--indra/newview/llpanelplaceprofile.cpp19
-rw-r--r--indra/newview/llpanelplaceprofile.h2
-rw-r--r--indra/newview/llpanelplaces.cpp188
-rw-r--r--indra/newview/llpanelplaces.h2
-rw-r--r--indra/newview/llparticipantlist.cpp11
-rw-r--r--indra/newview/llspeakers.cpp152
-rw-r--r--indra/newview/llspeakers.h94
-rw-r--r--indra/newview/lltexturectrl.cpp10
-rw-r--r--indra/newview/lltexturectrl.h3
-rw-r--r--indra/newview/lltransientdockablefloater.cpp1
-rw-r--r--indra/newview/lltransientdockablefloater.h4
-rw-r--r--indra/newview/lltransientfloatermgr.cpp75
-rw-r--r--indra/newview/lltransientfloatermgr.h47
-rw-r--r--indra/newview/llviewermessage.cpp7
-rw-r--r--indra/newview/skins/default/xui/en/favorites_bar_button.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_im_container.xml3
-rw-r--r--indra/newview/skins/default/xui/en/panel_bottomtray.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_roles.xml24
-rw-r--r--indra/newview/skins/default/xui/en/panel_my_profile.xml13
48 files changed, 853 insertions, 369 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index a4fc095727..c29a3a0035 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10070,6 +10070,18 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>SpeakerParticipantRemoveDelay</key>
+ <map>
+ <key>Comment</key>
+ <string>Timeout to remove participants who is not in channel before removed from list of active speakers (text/voice chat)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>10.0</real>
+ </map>
+
<key>UseStartScreen</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index f346a4b8c2..d4c8adadc6 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -93,22 +93,6 @@ static void* create_non_avatar_caller(void*)
return new LLNonAvatarCaller;
}
-LLCallFloater::LLAvatarListItemRemoveTimer::LLAvatarListItemRemoveTimer(callback_t remove_cb, F32 period, const LLUUID& speaker_id)
-: LLEventTimer(period)
-, mRemoveCallback(remove_cb)
-, mSpeakerId(speaker_id)
-{
-}
-
-BOOL LLCallFloater::LLAvatarListItemRemoveTimer::tick()
-{
- if (mRemoveCallback)
- {
- mRemoveCallback(mSpeakerId);
- }
- return TRUE;
-}
-
LLVoiceChannel* LLCallFloater::sCurrentVoiceCanel = NULL;
LLCallFloater::LLCallFloater(const LLSD& key)
@@ -122,10 +106,9 @@ LLCallFloater::LLCallFloater(const LLSD& key)
, mSpeakingIndicator(NULL)
, mIsModeratorMutedVoice(false)
, mInitParticipantsVoiceState(false)
-, mVoiceLeftRemoveDelay(10)
{
static LLUICachedControl<S32> voice_left_remove_delay ("VoiceParticipantLeftRemoveDelay", 10);
- mVoiceLeftRemoveDelay = voice_left_remove_delay;
+ mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLCallFloater::removeVoiceLeftParticipant, this, _1), voice_left_remove_delay);
mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL);
LLVoiceClient::getInstance()->addObserver(this);
@@ -135,6 +118,7 @@ LLCallFloater::LLCallFloater(const LLSD& key)
LLCallFloater::~LLCallFloater()
{
resetVoiceRemoveTimers();
+ delete mSpeakerDelayRemover;
delete mParticipants;
mParticipants = NULL;
@@ -648,33 +632,11 @@ void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state)
void LLCallFloater::setVoiceRemoveTimer(const LLUUID& voice_speaker_id)
{
-
- // If there is already a started timer for the current panel don't do anything.
- bool no_timer_for_current_panel = true;
- if (mVoiceLeftTimersMap.size() > 0)
- {
- timers_map::iterator found_it = mVoiceLeftTimersMap.find(voice_speaker_id);
- if (found_it != mVoiceLeftTimersMap.end())
- {
- no_timer_for_current_panel = false;
- }
- }
-
- if (no_timer_for_current_panel)
- {
- // Starting a timer to remove an avatar row panel after timeout
- mVoiceLeftTimersMap.insert(timer_pair(voice_speaker_id,
- new LLAvatarListItemRemoveTimer(boost::bind(&LLCallFloater::removeVoiceLeftParticipant, this, _1), mVoiceLeftRemoveDelay, voice_speaker_id)));
- }
+ mSpeakerDelayRemover->setActionTimer(voice_speaker_id);
}
-void LLCallFloater::removeVoiceLeftParticipant(const LLUUID& voice_speaker_id)
+bool LLCallFloater::removeVoiceLeftParticipant(const LLUUID& voice_speaker_id)
{
- if (mVoiceLeftTimersMap.size() > 0)
- {
- mVoiceLeftTimersMap.erase(mVoiceLeftTimersMap.find(voice_speaker_id));
- }
-
LLAvatarList::uuid_vector_t& speaker_uuids = mAvatarList->getIDs();
LLAvatarList::uuid_vector_t::iterator pos = std::find(speaker_uuids.begin(), speaker_uuids.end(), voice_speaker_id);
if(pos != speaker_uuids.end())
@@ -682,34 +644,19 @@ void LLCallFloater::removeVoiceLeftParticipant(const LLUUID& voice_speaker_id)
speaker_uuids.erase(pos);
mAvatarList->setDirty();
}
+
+ return false;
}
void LLCallFloater::resetVoiceRemoveTimers()
{
- if (mVoiceLeftTimersMap.size() > 0)
- {
- for (timers_map::iterator iter = mVoiceLeftTimersMap.begin();
- iter != mVoiceLeftTimersMap.end(); ++iter)
- {
- delete iter->second;
- }
- }
- mVoiceLeftTimersMap.clear();
+ mSpeakerDelayRemover->removeAllTimers();
}
void LLCallFloater::removeVoiceRemoveTimer(const LLUUID& voice_speaker_id)
{
- // Remove the timer if it has been already started
- if (mVoiceLeftTimersMap.size() > 0)
- {
- timers_map::iterator found_it = mVoiceLeftTimersMap.find(voice_speaker_id);
- if (found_it != mVoiceLeftTimersMap.end())
- {
- delete found_it->second;
- mVoiceLeftTimersMap.erase(found_it);
- }
- }
+ mSpeakerDelayRemover->unsetActionTimer(voice_speaker_id);
}
bool LLCallFloater::validateSpeaker(const LLUUID& speaker_id)
diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h
index 096594aaa2..eded3a426b 100644
--- a/indra/newview/llcallfloater.h
+++ b/indra/newview/llcallfloater.h
@@ -44,6 +44,8 @@ class LLNonAvatarCaller;
class LLOutputMonitorCtrl;
class LLParticipantList;
class LLSpeakerMgr;
+class LLSpeakersDelayActionsStorage;
+
/**
* The Voice Control Panel is an ambient window summoned by clicking the flyout chevron on the Speak button.
* It can be torn-off and freely positioned onscreen.
@@ -169,7 +171,7 @@ private:
*
* @param voice_speaker_id LLUUID of Avatar List item to be removed from the list.
*/
- void removeVoiceLeftParticipant(const LLUUID& voice_speaker_id);
+ bool removeVoiceLeftParticipant(const LLUUID& voice_speaker_id);
/**
* Deletes all timers from the list to prevent started timers from ticking after destruction
@@ -240,32 +242,11 @@ private:
boost::signals2::connection mAvatarListRefreshConnection;
+
/**
- * class LLAvatarListItemRemoveTimer
- *
- * Implements a timer that removes avatar list item of a participant
- * who has left the call.
+ * time out speakers when they are not part of current session
*/
- class LLAvatarListItemRemoveTimer : public LLEventTimer
- {
- public:
- typedef boost::function<void(const LLUUID&)> callback_t;
-
- LLAvatarListItemRemoveTimer(callback_t remove_cb, F32 period, const LLUUID& speaker_id);
- virtual ~LLAvatarListItemRemoveTimer() {};
-
- virtual BOOL tick();
-
- private:
- callback_t mRemoveCallback;
- LLUUID mSpeakerId;
- };
-
- typedef std::pair<LLUUID, LLAvatarListItemRemoveTimer*> timer_pair;
- typedef std::map<LLUUID, LLAvatarListItemRemoveTimer*> timers_map;
-
- timers_map mVoiceLeftTimersMap;
- S32 mVoiceLeftRemoveDelay;
+ LLSpeakersDelayActionsStorage* mSpeakerDelayRemover;
/**
* Stores reference to current voice channel.
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 8da207f887..f1de4e2982 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -1272,6 +1272,7 @@ bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index)
chiclet->setChicletSizeChangedCallback(boost::bind(&LLChicletPanel::onChicletSizeChanged, this, _1, index));
arrange();
+ LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, chiclet);
return true;
}
@@ -1299,6 +1300,7 @@ void LLChicletPanel::removeChiclet(chiclet_list_t::iterator it)
mChicletList.erase(it);
arrange();
+ LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, chiclet);
chiclet->die();
}
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index fb94657278..0e42ff09d8 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -51,6 +51,7 @@
#include "llinventorymodel.h"
#include "llfloaterworldmap.h"
#include "lllandmarkactions.h"
+#include "llnotificationsutil.h"
#include "llsidetray.h"
#include "lltoggleablemenu.h"
#include "llviewerinventory.h"
@@ -975,6 +976,10 @@ BOOL LLFavoritesBarCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
void copy_slurl_to_clipboard_cb(std::string& slurl)
{
gClipboard.copyFromString(utf8str_to_wstring(slurl));
+
+ LLSD args;
+ args["SLURL"] = slurl;
+ LLNotificationsUtil::add("CopySLURL", args);
}
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index e0f2fca580..2efae0c8db 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -277,13 +277,8 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
{
object_owner.append("Unknown");
}
- childSetText("object_name", object_owner);
- std::string owner_link =
- LLSLURL::buildCommand("agent", mObjectID, "inspect");
- childSetText("owner_name", owner_link);
- childSetText("abuser_name_edit", object_owner);
- mAbuserID = object_id;
- mOwnerName = object_owner;
+
+ setFromAvatar(object_id, object_owner);
}
else
{
@@ -305,7 +300,6 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
}
}
-
void LLFloaterReporter::onClickSelectAbuser()
{
gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), FALSE, TRUE ));
@@ -323,6 +317,17 @@ void LLFloaterReporter::callbackAvatarID(const std::vector<std::string>& names,
}
+void LLFloaterReporter::setFromAvatar(const LLUUID& avatar_id, const std::string& avatar_name)
+{
+ mAbuserID = mObjectID = avatar_id;
+ mOwnerName = avatar_name;
+
+ std::string avatar_link = LLSLURL::buildCommand("agent", mObjectID, "inspect");
+ childSetText("owner_name", avatar_link);
+ childSetText("object_name", avatar_name); // name
+ childSetText("abuser_name_edit", avatar_name);
+}
+
// static
void LLFloaterReporter::onClickSend(void *userdata)
{
@@ -458,9 +463,8 @@ void LLFloaterReporter::showFromMenu(EReportType report_type)
}
}
-
// static
-void LLFloaterReporter::showFromObject(const LLUUID& object_id)
+void LLFloaterReporter::show(const LLUUID& object_id, const std::string& avatar_name)
{
LLFloaterReporter* f = LLFloaterReg::showTypedInstance<LLFloaterReporter>("reporter");
@@ -469,8 +473,11 @@ void LLFloaterReporter::showFromObject(const LLUUID& object_id)
LLAgentUI::buildFullname(fullname);
f->childSetText("reporter_field", fullname);
- // Request info for this object
- f->getObjectInfo(object_id);
+ if (avatar_name.empty())
+ // Request info for this object
+ f->getObjectInfo(object_id);
+ else
+ f->setFromAvatar(object_id, avatar_name);
// Need to deselect on close
f->mDeselectOnClose = TRUE;
@@ -479,6 +486,18 @@ void LLFloaterReporter::showFromObject(const LLUUID& object_id)
}
+// static
+void LLFloaterReporter::showFromObject(const LLUUID& object_id)
+{
+ show(object_id);
+}
+
+// static
+void LLFloaterReporter::showFromAvatar(const LLUUID& avatar_id, const std::string avatar_name)
+{
+ show(avatar_id, avatar_name);
+}
+
void LLFloaterReporter::setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id)
{
childSetText("object_name", object_name);
diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h
index cc2dfb2f98..7c6473f975 100644
--- a/indra/newview/llfloaterreporter.h
+++ b/indra/newview/llfloaterreporter.h
@@ -93,6 +93,7 @@ public:
static void showFromMenu(EReportType report_type);
static void showFromObject(const LLUUID& object_id);
+ static void showFromAvatar(const LLUUID& avatar_id, const std::string avatar_name);
static void onClickSend (void *userdata);
static void onClickCancel (void *userdata);
@@ -109,6 +110,8 @@ public:
void setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id);
private:
+ static void show(const LLUUID& object_id, const std::string& avatar_name = LLStringUtil::null);
+
void takeScreenshot();
void sendReportViaCaps(std::string url);
void uploadImage();
@@ -121,6 +124,7 @@ private:
void enableControls(BOOL own_avatar);
void getObjectInfo(const LLUUID& object_id);
void callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids);
+ void setFromAvatar(const LLUUID& avatar_id, const std::string& avatar_name = LLStringUtil::null);
private:
EReportType mReportType;
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index a63fb73032..b833c611bf 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -1391,6 +1391,7 @@ void LLFolderView::startRenamingSelectedItem( void )
// set focus will fail unless item is visible
mRenamer->setFocus( TRUE );
mRenamer->setTopLostCallback(boost::bind(onRenamerLost, _1));
+ mRenamer->setFocusLostCallback(boost::bind(onRenamerLost, _1));
gFocusMgr.setTopCtrl( mRenamer );
}
}
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index e06e0c94ec..73597e7de3 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -110,6 +110,8 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
}
}
setOverlapsScreenChannel(true);
+
+ LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this);
}
void LLIMFloater::onFocusLost()
@@ -228,6 +230,7 @@ void LLIMFloater::sendMsg()
LLIMFloater::~LLIMFloater()
{
+ LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this);
}
//virtual
@@ -513,14 +516,14 @@ bool LLIMFloater::toggle(const LLUUID& session_id)
if(!isChatMultiTab())
{
LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
- if (floater && floater->getVisible())
+ if (floater && floater->getVisible() && floater->hasFocus())
{
// clicking on chiclet to close floater just hides it to maintain existing
// scroll/text entry state
floater->setVisible(false);
return false;
}
- else if(floater && !floater->isDocked())
+ else if(floater && (!floater->isDocked() || floater->getVisible() && !floater->hasFocus()))
{
floater->setVisible(TRUE);
floater->setFocus(TRUE);
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index d9db385d06..0ca0325451 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -116,6 +116,8 @@ public:
static void onIMChicletCreated(const LLUUID& session_id);
+ virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; }
+
private:
// process focus events to set a currently active session
/* virtual */ void onFocusLost();
diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp
index 6cc985aef4..06a7b4a29c 100644
--- a/indra/newview/llimfloatercontainer.cpp
+++ b/indra/newview/llimfloatercontainer.cpp
@@ -35,19 +35,22 @@
#include "llimfloatercontainer.h"
#include "llfloaterreg.h"
+#include "llimview.h"
+#include "llavatariconctrl.h"
+#include "llagent.h"
//
// LLIMFloaterContainer
//
LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed)
-: LLMultiFloater(seed),
- mActiveVoiceFloater(NULL)
+: LLMultiFloater(seed)
{
mAutoResize = FALSE;
}
LLIMFloaterContainer::~LLIMFloaterContainer()
{
+ LLGroupMgr::getInstance()->removeObserver(this);
}
BOOL LLIMFloaterContainer::postBuild()
@@ -87,13 +90,84 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp,
LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point);
- // make sure active voice icon shows up for new tab
- if (floaterp == mActiveVoiceFloater)
+ LLUUID session_id = floaterp->getKey();
+
+ if(gAgent.isInGroup(session_id))
+ {
+ mSessions[session_id] = floaterp;
+ mID = session_id;
+ mGroupID.push_back(session_id);
+ LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(session_id);
+ LLGroupMgr* gm = LLGroupMgr::getInstance();
+ gm->addObserver(this);
+
+ if (group_data && group_data->mInsigniaID.notNull())
+ {
+ mTabContainer->setTabImage(get_ptr_in_map(mSessions, session_id), group_data->mInsigniaID);
+ }
+ else
+ {
+ gm->sendGroupPropertiesRequest(session_id);
+ }
+ }
+ else
+ {
+ LLUUID avatar_id = LLIMModel::getInstance()->getOtherParticipantID(session_id);
+ LLAvatarPropertiesProcessor& app = LLAvatarPropertiesProcessor::instance();
+ app.addObserver(avatar_id, this);
+ floaterp->mCloseSignal.connect(boost::bind(&LLIMFloaterContainer::onCloseFloater, this, avatar_id));
+ mSessions[avatar_id] = floaterp;
+
+ LLUUID* icon_id_ptr = LLAvatarIconIDCache::getInstance()->get(avatar_id);
+ if(!icon_id_ptr)
+ {
+ app.sendAvatarPropertiesRequest(avatar_id);
+ }
+ else
+ {
+ mTabContainer->setTabImage(floaterp, *icon_id_ptr);
+ }
+ }
+}
+
+void LLIMFloaterContainer::processProperties(void* data, enum EAvatarProcessorType type)
+{
+ if (APT_PROPERTIES == type)
+ {
+ LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data);
+ if (avatar_data)
+ {
+ LLUUID avatar_id = avatar_data->avatar_id;
+ if(avatar_data->image_id != *LLAvatarIconIDCache::getInstance()->get(avatar_id))
+ {
+ LLAvatarIconIDCache::getInstance()->add(avatar_id,avatar_data->image_id);
+ }
+ mTabContainer->setTabImage(get_ptr_in_map(mSessions, avatar_id), avatar_data->image_id);
+ }
+ }
+}
+
+void LLIMFloaterContainer::changed(LLGroupChange gc)
+{
+ if (GC_PROPERTIES == gc)
{
- mTabContainer->setTabImage(floaterp, "active_voice_tab.tga");
+ for(groupIDs_t::iterator it = mGroupID.begin(); it!=mGroupID.end(); it++)
+ {
+ LLUUID group_id = *it;
+ LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(group_id);
+ if (group_data && group_data->mInsigniaID.notNull())
+ {
+ mTabContainer->setTabImage(get_ptr_in_map(mSessions, group_id), group_data->mInsigniaID);
+ }
+ }
}
}
+void LLIMFloaterContainer::onCloseFloater(LLUUID id)
+{
+ LLAvatarPropertiesProcessor::instance().removeObserver(id, this);
+}
+
LLIMFloaterContainer* LLIMFloaterContainer::findInstance()
{
return LLFloaterReg::findTypedInstance<LLIMFloaterContainer>("im_container");
diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h
index d4a542dfc2..1333b098bc 100644
--- a/indra/newview/llimfloatercontainer.h
+++ b/indra/newview/llimfloatercontainer.h
@@ -33,12 +33,17 @@
#ifndef LL_LLIMFLOATERCONTAINER_H
#define LL_LLIMFLOATERCONTAINER_H
+#include <map>
+#include <vector>
+
#include "llfloater.h"
#include "llmultifloater.h"
+#include "llavatarpropertiesprocessor.h"
+#include "llgroupmgr.h"
class LLTabContainer;
-class LLIMFloaterContainer : public LLMultiFloater
+class LLIMFloaterContainer : public LLMultiFloater, public LLAvatarPropertiesObserver, public LLGroupMgrObserver
{
public:
LLIMFloaterContainer(const LLSD& seed);
@@ -51,15 +56,23 @@ public:
BOOL select_added_floater,
LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END);
+ void processProperties(void* data, EAvatarProcessorType type);
+ void changed(LLGroupChange gc);
+
static LLFloater* getCurrentVoiceFloater();
static LLIMFloaterContainer* findInstance();
static LLIMFloaterContainer* getInstance();
-protected:
-
- LLFloater* mActiveVoiceFloater;
+private:
+ typedef std::map<LLUUID,LLPanel*> avatarID_panel_map_t;
+ avatarID_panel_map_t mSessions;
+
+ typedef std::vector<LLUUID> groupIDs_t;
+ groupIDs_t mGroupID;
+
+ void onCloseFloater(LLUUID avatar_id);
};
#endif // LL_LLIMFLOATERCONTAINER_H
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index ff20a55358..c2a7969c0d 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -55,6 +55,7 @@
#include "llfloaterchatterbox.h"
#include "llimfloater.h"
#include "llgroupiconctrl.h"
+#include "llmd5.h"
#include "llmutelist.h"
#include "llrecentpeople.h"
#include "llviewermessage.h"
@@ -215,12 +216,14 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&
mTextIMPossible = LLVoiceClient::getInstance()->isSessionTextIMPossible(mSessionID);
}
+ buildHistoryFileName();
+
if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
{
std::list<LLSD> chat_history;
//involves parsing of a chat history
- LLLogChat::loadAllHistory(mName, chat_history);
+ LLLogChat::loadAllHistory(mHistoryFileName, chat_history);
addMessagesFromHistory(chat_history);
}
}
@@ -467,6 +470,44 @@ bool LLIMModel::LLIMSession::isOtherParticipantAvaline()
return !mOtherParticipantIsAvatar;
}
+void LLIMModel::LLIMSession::buildHistoryFileName()
+{
+ mHistoryFileName = mName;
+
+ //ad-hoc requires sophisticated chat history saving schemes
+ if (isAdHoc())
+ {
+ //in case of outgoing ad-hoc sessions
+ if (mInitialTargetIDs.size())
+ {
+ std::set<LLUUID> sorted_uuids(mInitialTargetIDs.begin(), mInitialTargetIDs.end());
+ mHistoryFileName = mName + " hash" + generateHash(sorted_uuids);
+ return;
+ }
+
+ //in case of incoming ad-hoc sessions
+ mHistoryFileName = mName + " " + LLLogChat::timestamp(true) + " " + mSessionID.asString().substr(0, 4);
+ }
+}
+
+//static
+std::string LLIMModel::LLIMSession::generateHash(const std::set<LLUUID>& sorted_uuids)
+{
+ LLMD5 md5_uuid;
+
+ std::set<LLUUID>::const_iterator it = sorted_uuids.begin();
+ while (it != sorted_uuids.end())
+ {
+ md5_uuid.update((unsigned char*)(*it).mData, 16);
+ it++;
+ }
+ md5_uuid.finalize();
+
+ LLUUID participants_md5_hash;
+ md5_uuid.raw_digest((unsigned char*) participants_md5_hash.mData);
+ return participants_md5_hash.asString();
+}
+
void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, const LLUUID& new_session_id)
{
@@ -614,11 +655,11 @@ bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from,
return true;
}
-bool LLIMModel::logToFile(const std::string& session_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text)
+bool LLIMModel::logToFile(const std::string& file_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text)
{
if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
{
- LLLogChat::saveHistory(session_name, from, from_id, utf8_text);
+ LLLogChat::saveHistory(file_name, from, from_id, utf8_text);
return true;
}
else
@@ -629,15 +670,7 @@ bool LLIMModel::logToFile(const std::string& session_name, const std::string& fr
bool LLIMModel::logToFile(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text)
{
- if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
- {
- LLLogChat::saveHistory(LLIMModel::getInstance()->getName(session_id), from, from_id, utf8_text);
- return true;
- }
- else
- {
- return false;
- }
+ return logToFile(LLIMModel::getInstance()->getHistoryFileName(session_id), from, from_id, utf8_text);
}
bool LLIMModel::proccessOnlineOfflineNotification(
@@ -782,6 +815,18 @@ LLIMSpeakerMgr* LLIMModel::getSpeakerManager( const LLUUID& session_id ) const
return session->mSpeakers;
}
+const std::string& LLIMModel::getHistoryFileName(const LLUUID& session_id) const
+{
+ LLIMSession* session = findIMSession(session_id);
+ if (!session)
+ {
+ llwarns << "session " << session_id << " does not exist " << llendl;
+ return LLStringUtil::null;
+ }
+
+ return session->mHistoryFileName;
+}
+
// TODO get rid of other participant ID
void LLIMModel::sendTypingState(LLUUID session_id, LLUUID other_participant_id, BOOL typing)
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index a226d66b12..a3b4f78af0 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -69,6 +69,8 @@ public:
void addMessagesFromHistory(const std::list<LLSD>& history);
void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time);
void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction);
+
+ /** @deprecated */
static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata);
bool isAdHoc();
@@ -80,12 +82,20 @@ public:
bool isGroupSessionType() const { return mSessionType == GROUP_SESSION;}
bool isAvalineSessionType() const { return mSessionType == AVALINE_SESSION;}
+ //*TODO make private
+ /** ad-hoc sessions involve sophisticated chat history file naming schemes */
+ void buildHistoryFileName();
+
+ //*TODO make private
+ static std::string generateHash(const std::set<LLUUID>& sorted_uuids);
+
LLUUID mSessionID;
std::string mName;
EInstantMessage mType;
SType mSessionType;
LLUUID mOtherParticipantID;
std::vector<LLUUID> mInitialTargetIDs;
+ std::string mHistoryFileName;
// connection to voice channel state change signal
boost::signals2::connection mVoiceChannelStateChangeConnection;
@@ -231,6 +241,8 @@ public:
*/
LLIMSpeakerMgr* getSpeakerManager(const LLUUID& session_id) const;
+ const std::string& getHistoryFileName(const LLUUID& session_id) const;
+
static void sendLeaveSession(const LLUUID& session_id, const LLUUID& other_participant_id);
static bool sendStartSession(const LLUUID& temp_session_id, const LLUUID& other_participant_id,
const std::vector<LLUUID>& ids, EInstantMessage dialog);
@@ -243,7 +255,7 @@ public:
/**
* Saves an IM message into a file
*/
- bool logToFile(const std::string& session_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text);
+ bool logToFile(const std::string& file_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text);
private:
diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp
index 0374a1d25b..4b0539337b 100644
--- a/indra/newview/llinspectavatar.cpp
+++ b/indra/newview/llinspectavatar.cpp
@@ -689,7 +689,7 @@ void LLInspectAvatar::onToggleMute()
void LLInspectAvatar::onClickReport()
{
- LLFloaterReporter::showFromObject(mAvatarID);
+ LLFloaterReporter::showFromAvatar(mAvatarID, mAvatarName);
closeFloater();
}
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 1b1f615a57..f91bbaff68 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -3687,18 +3687,6 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
return rv;
}
-BOOL LLCallingCardBridge::removeItem()
-{
- if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem()))
- {
- LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID());
- return FALSE;
- }
- else
- {
- return LLItemBridge::removeItem();
- }
-}
// +=================================================+
// | LLNotecardBridge |
// +=================================================+
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index fced0047e8..759d0cba18 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -448,7 +448,6 @@ public:
EDragAndDropType cargo_type,
void* cargo_data);
void refreshFolderViewItem();
- BOOL removeItem();
protected:
LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid );
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 404e266806..7f49a7defb 100644
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -43,8 +43,11 @@
#include "lltrans.h"
#include "lluictrlfactory.h"
#include "lltooltip.h"
+#include "llnotificationsutil.h"
+#include "llregionflags.h"
// newview includes
+#include "llagent.h"
#include "llinventoryobserver.h"
#include "lllandmarkactions.h"
#include "lllandmarklist.h"
@@ -56,6 +59,7 @@
#include "lltrans.h"
#include "llviewerinventory.h"
#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
#include "llviewercontrol.h"
#include "llviewermenu.h"
#include "llurllineeditorctrl.h"
@@ -256,36 +260,42 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p)
voice_icon.tool_tip = LLTrans::getString("LocationCtrlVoiceTooltip");
voice_icon.mouse_opaque = true;
mParcelIcon[VOICE_ICON] = LLUICtrlFactory::create<LLIconCtrl>(voice_icon);
+ mParcelIcon[VOICE_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, VOICE_ICON));
addChild(mParcelIcon[VOICE_ICON]);
LLIconCtrl::Params fly_icon = p.fly_icon;
fly_icon.tool_tip = LLTrans::getString("LocationCtrlFlyTooltip");
fly_icon.mouse_opaque = true;
mParcelIcon[FLY_ICON] = LLUICtrlFactory::create<LLIconCtrl>(fly_icon);
+ mParcelIcon[FLY_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, FLY_ICON));
addChild(mParcelIcon[FLY_ICON]);
LLIconCtrl::Params push_icon = p.push_icon;
push_icon.tool_tip = LLTrans::getString("LocationCtrlPushTooltip");
push_icon.mouse_opaque = true;
mParcelIcon[PUSH_ICON] = LLUICtrlFactory::create<LLIconCtrl>(push_icon);
+ mParcelIcon[PUSH_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, PUSH_ICON));
addChild(mParcelIcon[PUSH_ICON]);
LLIconCtrl::Params build_icon = p.build_icon;
build_icon.tool_tip = LLTrans::getString("LocationCtrlBuildTooltip");
build_icon.mouse_opaque = true;
mParcelIcon[BUILD_ICON] = LLUICtrlFactory::create<LLIconCtrl>(build_icon);
+ mParcelIcon[BUILD_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, BUILD_ICON));
addChild(mParcelIcon[BUILD_ICON]);
LLIconCtrl::Params scripts_icon = p.scripts_icon;
scripts_icon.tool_tip = LLTrans::getString("LocationCtrlScriptsTooltip");
scripts_icon.mouse_opaque = true;
mParcelIcon[SCRIPTS_ICON] = LLUICtrlFactory::create<LLIconCtrl>(scripts_icon);
+ mParcelIcon[SCRIPTS_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, SCRIPTS_ICON));
addChild(mParcelIcon[SCRIPTS_ICON]);
LLIconCtrl::Params damage_icon = p.damage_icon;
damage_icon.tool_tip = LLTrans::getString("LocationCtrlDamageTooltip");
damage_icon.mouse_opaque = true;
mParcelIcon[DAMAGE_ICON] = LLUICtrlFactory::create<LLIconCtrl>(damage_icon);
+ mParcelIcon[DAMAGE_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, DAMAGE_ICON));
addChild(mParcelIcon[DAMAGE_ICON]);
LLTextBox::Params damage_text = p.damage_text;
@@ -918,3 +928,45 @@ bool LLLocationInputCtrl::onLocationContextMenuItemEnabled(const LLSD& userdata)
return false;
}
+
+void LLLocationInputCtrl::onParcelIconClick(EParcelIcon icon)
+{
+ switch (icon)
+ {
+ case VOICE_ICON:
+ LLNotificationsUtil::add("NoVoice");
+ break;
+ case FLY_ICON:
+ LLNotificationsUtil::add("NoFly");
+ break;
+ case PUSH_ICON:
+ LLNotificationsUtil::add("PushRestricted");
+ break;
+ case BUILD_ICON:
+ LLNotificationsUtil::add("NoBuild");
+ break;
+ case SCRIPTS_ICON:
+ {
+ LLViewerRegion* region = gAgent.getRegion();
+ if(region && region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS)
+ {
+ LLNotificationsUtil::add("ScriptsStopped");
+ }
+ else if(region && region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS)
+ {
+ LLNotificationsUtil::add("ScriptsNotRunning");
+ }
+ else
+ {
+ LLNotificationsUtil::add("NoOutsideScripts");
+ }
+ break;
+ }
+ case DAMAGE_ICON:
+ LLNotificationsUtil::add("NotSafe");
+ break;
+ case ICON_COUNT:
+ break;
+ // no default to get compiler warning when a new icon gets added
+ }
+}
diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h
index 7959fab2de..607ccd4da6 100644
--- a/indra/newview/lllocationinputctrl.h
+++ b/indra/newview/lllocationinputctrl.h
@@ -102,6 +102,18 @@ public:
void handleLoginComplete();
private:
+
+ enum EParcelIcon
+ {
+ VOICE_ICON = 0,
+ FLY_ICON,
+ PUSH_ICON,
+ BUILD_ICON,
+ SCRIPTS_ICON,
+ DAMAGE_ICON,
+ ICON_COUNT
+ };
+
friend class LLUICtrlFactory;
LLLocationInputCtrl(const Params&);
virtual ~LLLocationInputCtrl();
@@ -138,6 +150,7 @@ private:
// callbacks
bool onLocationContextMenuItemEnabled(const LLSD& userdata);
void onLocationContextMenuItemClicked(const LLSD& userdata);
+ void onParcelIconClick(EParcelIcon icon);
LLMenuGL* mLocationContextMenu;
LLButton* mAddLandmarkBtn;
@@ -146,16 +159,6 @@ private:
S32 mIconHPad; // pad between all icons
S32 mAddLandmarkHPad; // pad to left of landmark star
- enum EParcelIcon
- {
- VOICE_ICON = 0,
- FLY_ICON,
- PUSH_ICON,
- BUILD_ICON,
- SCRIPTS_ICON,
- DAMAGE_ICON,
- ICON_COUNT
- };
LLIconCtrl* mParcelIcon[ICON_COUNT];
LLTextBox* mDamageText;
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 4e5aaeb66a..dc187bf36c 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -237,15 +237,15 @@ void append_to_last_message(std::list<LLSD>& messages, const std::string& line)
messages.back()[IM_TEXT] = im_text;
}
-void LLLogChat::loadAllHistory(const std::string& session_name, std::list<LLSD>& messages)
+void LLLogChat::loadAllHistory(const std::string& file_name, std::list<LLSD>& messages)
{
- if (session_name.empty())
+ if (file_name.empty())
{
llwarns << "Session name is Empty!" << llendl;
return ;
}
- LLFILE* fptr = LLFile::fopen(makeLogFileName(session_name), "r"); /*Flawfinder: ignore*/
+ LLFILE* fptr = LLFile::fopen(makeLogFileName(file_name), "r"); /*Flawfinder: ignore*/
if (!fptr) return; //No previous conversation with this name.
char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index 3d3f5c4458..4290e4bbc0 100644
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -56,7 +56,7 @@ public:
void (*callback)(ELogLineType, const LLSD&, void*),
void* userdata);
- static void loadAllHistory(const std::string& session_name, std::list<LLSD>& messages);
+ static void loadAllHistory(const std::string& file_name, std::list<LLSD>& messages);
private:
static std::string cleanFileName(std::string filename);
};
diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp
index 569d3001bf..c30ef3221d 100644
--- a/indra/newview/llpanelgroup.cpp
+++ b/indra/newview/llpanelgroup.cpp
@@ -356,13 +356,6 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
for(std::vector<LLPanelGroupTab* >::iterator it = mTabs.begin();it!=mTabs.end();++it)
(*it)->setGroupID(group_id);
- LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID);
- if(gdatap)
- {
- childSetValue("group_name", gdatap->mName);
- childSetToolTip("group_name",gdatap->mName);
- }
-
LLButton* button_apply = findChild<LLButton>("btn_apply");
LLButton* button_refresh = findChild<LLButton>("btn_refresh");
LLButton* button_create = findChild<LLButton>("btn_create");
@@ -464,6 +457,17 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
}
reposButtons();
+
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID);
+
+ if(gdatap)
+ {
+ childSetValue("group_name", gdatap->mName);
+ childSetToolTip("group_name",gdatap->mName);
+
+ //group data is already present, call update manually
+ update(GC_ALL);
+ }
}
bool LLPanelGroup::apply(LLPanelGroupTab* tab)
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 0e55ff3214..45f0381d6f 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -452,6 +452,7 @@ LLPanelGroupSubTab::LLPanelGroupSubTab()
: LLPanelGroupTab(),
mHeader(NULL),
mFooter(NULL),
+ mActivated(false),
mSearchEditor(NULL)
{
}
@@ -504,13 +505,14 @@ void LLPanelGroupSubTab::setGroupID(const LLUUID& id)
mSearchEditor->clear();
setSearchFilter("");
}
+
+ mActivated = false;
}
void LLPanelGroupSubTab::setSearchFilter(const std::string& filter)
{
if(mSearchFilter == filter)
return;
- lldebugs << "LLPanelGroupSubTab::setSearchFilter() ==> '" << filter << "'" << llendl;
mSearchFilter = filter;
LLStringUtil::toLower(mSearchFilter);
update(GC_ALL);
@@ -518,13 +520,11 @@ void LLPanelGroupSubTab::setSearchFilter(const std::string& filter)
void LLPanelGroupSubTab::activate()
{
- lldebugs << "LLPanelGroupSubTab::activate()" << llendl;
setOthersVisible(TRUE);
}
void LLPanelGroupSubTab::deactivate()
{
- lldebugs << "LLPanelGroupSubTab::deactivate()" << llendl;
setOthersVisible(FALSE);
}
@@ -534,19 +534,11 @@ void LLPanelGroupSubTab::setOthersVisible(BOOL b)
{
mHeader->setVisible( b );
}
- else
- {
- llwarns << "LLPanelGroupSubTab missing header!" << llendl;
- }
if (mFooter)
{
mFooter->setVisible( b );
}
- else
- {
- llwarns << "LLPanelGroupSubTab missing footer!" << llendl;
- }
}
bool LLPanelGroupSubTab::matchesActionSearchFilter(std::string action)
@@ -875,10 +867,12 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
for (itor = selection.begin();
itor != selection.end(); ++itor)
{
- selected_members.push_back( (*itor)->getUUID() );
+ LLUUID member_id = (*itor)->getValue()["uuid"];
+
+ selected_members.push_back( member_id );
// Get this member's power mask including any unsaved changes
- U64 powers = getAgentPowersBasedOnRoleChanges((*itor)->getUUID());
+ U64 powers = getAgentPowersBasedOnRoleChanges( member_id );
allowed_by_all &= powers;
allowed_by_some |= powers;
@@ -1022,6 +1016,7 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
//last owner. We should check for this special case
// -jwolk
check->setEnabled(cb_enable);
+ item->setEnabled(cb_enable);
}
}
else
@@ -1098,7 +1093,8 @@ void LLPanelGroupMembersSubTab::handleEjectMembers()
for (itor = selection.begin() ;
itor != selection.end(); ++itor)
{
- selected_members.push_back((*itor)->getUUID());
+ LLUUID member_id = (*itor)->getValue()["uuid"];
+ selected_members.push_back( member_id );
}
mMembersList->deleteSelectedItems();
@@ -1154,7 +1150,8 @@ void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,
for (std::vector<LLScrollListItem*>::iterator itor = selection.begin() ;
itor != selection.end(); ++itor)
{
- member_id = (*itor)->getUUID();
+
+ member_id = (*itor)->getValue()["uuid"];
//see if we requested a change for this member before
if ( mMemberRoleChangeData.find(member_id) == mMemberRoleChangeData.end() )
@@ -1245,15 +1242,19 @@ void LLPanelGroupMembersSubTab::handleMemberDoubleClick()
LLScrollListItem* selected = mMembersList->getFirstSelected();
if (selected)
{
- LLAvatarActions::showProfile(selected->getUUID());
+ LLUUID member_id = selected->getValue()["uuid"];
+ LLAvatarActions::showProfile( member_id );
}
}
void LLPanelGroupMembersSubTab::activate()
{
LLPanelGroupSubTab::activate();
-
- update(GC_ALL);
+ if(!mActivated)
+ {
+ update(GC_ALL);
+ mActivated = true;
+ }
}
void LLPanelGroupMembersSubTab::deactivate()
@@ -1629,7 +1630,9 @@ void LLPanelGroupMembersSubTab::updateMembers()
row["columns"][2]["value"] = mMemberProgress->second->getOnlineStatus();
row["columns"][2]["font"] = "SANSSERIF_SMALL";
- mMembersList->addElement(row);//, ADD_SORTED);
+ LLScrollListItem* member = mMembersList->addElement(row);//, ADD_SORTED);
+
+ LLUUID id = member->getValue()["uuid"];
mHasMatch = TRUE;
}
}
diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h
index 2f81900e60..eac22a6338 100644
--- a/indra/newview/llpanelgrouproles.h
+++ b/indra/newview/llpanelgrouproles.h
@@ -149,6 +149,8 @@ protected:
icon_map_t mActionIcons;
+ bool mActivated;
+
void setOthersVisible(BOOL b);
};
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index b1cdb4d81f..a334eb9d68 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -245,7 +245,6 @@ void LLPanelIMControlPanel::nameUpdatedCallback(const LLUUID& id, const std::str
LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id):
mParticipantList(NULL)
{
- mSpeakerManager = LLIMModel::getInstance()->getSpeakerManager(session_id);
}
BOOL LLPanelGroupControlPanel::postBuild()
@@ -264,9 +263,6 @@ LLPanelGroupControlPanel::~LLPanelGroupControlPanel()
// virtual
void LLPanelGroupControlPanel::draw()
{
- //Remove event does not raised until speakerp->mActivityTimer.hasExpired() is false, see LLSpeakerManager::update()
- //so we need update it to raise needed event
- mSpeakerManager->update(true);
// Need to resort the participant list if it's in sort by recent speaker order.
if (mParticipantList)
mParticipantList->updateRecentSpeakersOrder();
@@ -307,7 +303,10 @@ void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id)
// for group and Ad-hoc chat we need to include agent into list
if(!mParticipantList)
- mParticipantList = new LLParticipantList(mSpeakerManager, getChild<LLAvatarList>("speakers_list"), true,false);
+ {
+ LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(session_id);
+ mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true,false);
+ }
}
diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h
index c18be5a6df..25fdf944c9 100644
--- a/indra/newview/llpanelimcontrolpanel.h
+++ b/indra/newview/llpanelimcontrolpanel.h
@@ -37,8 +37,6 @@
#include "llvoicechannel.h"
#include "llcallingcard.h"
-class LLSpeakerMgr;
-class LLAvatarList;
class LLParticipantList;
class LLPanelChatControlPanel : public LLPanel
@@ -110,7 +108,6 @@ public:
protected:
LLUUID mGroupID;
- LLSpeakerMgr* mSpeakerManager;
LLParticipantList* mParticipantList;
diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp
index b80eb9db38..0c10f11bfc 100644
--- a/indra/newview/llpanelplaceinfo.cpp
+++ b/indra/newview/llpanelplaceinfo.cpp
@@ -34,26 +34,20 @@
#include "llpanelplaceinfo.h"
-#include "roles_constants.h"
#include "llsdutil.h"
-#include "llsecondlifeurls.h"
#include "llsdutil_math.h"
+
#include "llregionhandle.h"
-#include "message.h"
#include "lliconctrl.h"
#include "lltextbox.h"
#include "llagent.h"
-#include "llavatarpropertiesprocessor.h"
#include "llexpandabletextbox.h"
#include "llpanelpick.h"
#include "lltexturectrl.h"
-#include "llviewerinventory.h"
-#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
-#include "llviewertexteditor.h"
LLPanelPlaceInfo::LLPanelPlaceInfo()
: LLPanel(),
@@ -265,25 +259,6 @@ void LLPanelPlaceInfo::reshape(S32 width, S32 height, BOOL called_from_parent)
}
}
-// virtual
-void LLPanelPlaceInfo::handleVisibilityChange(BOOL new_visibility)
-{
- LLPanel::handleVisibilityChange(new_visibility);
-
- LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
- if (!parcel_mgr)
- return;
-
- // Remove land selection when panel hides.
- if (!new_visibility)
- {
- if (!parcel_mgr->selectionEmpty())
- {
- parcel_mgr->deselectLand();
- }
- }
-}
-
void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPickEdit* pick_panel)
{
std::string region_name = mRegionName->getText();
diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h
index 7dfc7b2444..3091f7ed24 100644
--- a/indra/newview/llpanelplaceinfo.h
+++ b/indra/newview/llpanelplaceinfo.h
@@ -94,7 +94,6 @@ public:
/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
- /*virtual*/ void handleVisibilityChange (BOOL new_visibility);
// Create a pick for the location specified
// by global_pos.
diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp
index 402d50ba9c..d892e2885b 100644
--- a/indra/newview/llpanelplaceprofile.cpp
+++ b/indra/newview/llpanelplaceprofile.cpp
@@ -257,6 +257,25 @@ void LLPanelPlaceProfile::processParcelInfo(const LLParcelData& parcel_data)
}
}
+// virtual
+void LLPanelPlaceProfile::handleVisibilityChange(BOOL new_visibility)
+{
+ LLPanel::handleVisibilityChange(new_visibility);
+
+ LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
+ if (!parcel_mgr)
+ return;
+
+ // Remove land selection when panel hides.
+ if (!new_visibility)
+ {
+ if (!parcel_mgr->selectionEmpty())
+ {
+ parcel_mgr->deselectUnused();
+ }
+ }
+}
+
void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
LLViewerRegion* region,
const LLVector3d& pos_global,
diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h
index 8c30ca92fb..8ca9526875 100644
--- a/indra/newview/llpanelplaceprofile.h
+++ b/indra/newview/llpanelplaceprofile.h
@@ -52,6 +52,8 @@ public:
/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
+ /*virtual*/ void handleVisibilityChange(BOOL new_visibility);
+
// Displays information about the currently selected parcel
// without sending a request to the server.
// If is_current_parcel true shows "You Are Here" banner.
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index b037674c37..a4f0e55a93 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -289,89 +289,92 @@ BOOL LLPanelPlaces::postBuild()
void LLPanelPlaces::onOpen(const LLSD& key)
{
- if(!mPlaceProfile || !mLandmarkInfo || key.size() == 0)
+ if (!mPlaceProfile || !mLandmarkInfo)
return;
- mFilterEditor->clear();
- onFilterEdit("", false);
-
- mPlaceInfoType = key["type"].asString();
- mPosGlobal.setZero();
- mItem = NULL;
- isLandmarkEditModeOn = false;
- togglePlaceInfoPanel(TRUE);
-
- if (mPlaceInfoType == AGENT_INFO_TYPE)
- {
- mPlaceProfile->setInfoType(LLPanelPlaceInfo::AGENT);
- }
- else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
+ if (key.size() != 0)
{
- mLandmarkInfo->setInfoType(LLPanelPlaceInfo::CREATE_LANDMARK);
+ mFilterEditor->clear();
+ onFilterEdit("", false);
- if (key.has("x") && key.has("y") && key.has("z"))
+ mPlaceInfoType = key["type"].asString();
+ mPosGlobal.setZero();
+ mItem = NULL;
+ isLandmarkEditModeOn = false;
+ togglePlaceInfoPanel(TRUE);
+
+ if (mPlaceInfoType == AGENT_INFO_TYPE)
{
- mPosGlobal = LLVector3d(key["x"].asReal(),
- key["y"].asReal(),
- key["z"].asReal());
+ mPlaceProfile->setInfoType(LLPanelPlaceInfo::AGENT);
}
- else
+ else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
{
- mPosGlobal = gAgent.getPositionGlobal();
- }
-
- mLandmarkInfo->displayParcelInfo(LLUUID(), mPosGlobal);
+ mLandmarkInfo->setInfoType(LLPanelPlaceInfo::CREATE_LANDMARK);
- // Disable Save button because there is no item to save yet.
- // The button will be enabled in onLandmarkLoaded callback.
- mSaveBtn->setEnabled(FALSE);
- }
- else if (mPlaceInfoType == LANDMARK_INFO_TYPE)
- {
- mLandmarkInfo->setInfoType(LLPanelPlaceInfo::LANDMARK);
+ if (key.has("x") && key.has("y") && key.has("z"))
+ {
+ mPosGlobal = LLVector3d(key["x"].asReal(),
+ key["y"].asReal(),
+ key["z"].asReal());
+ }
+ else
+ {
+ mPosGlobal = gAgent.getPositionGlobal();
+ }
- LLInventoryItem* item = gInventory.getItem(key["id"].asUUID());
- if (!item)
- return;
+ mLandmarkInfo->displayParcelInfo(LLUUID(), mPosGlobal);
- setItem(item);
- }
- else if (mPlaceInfoType == REMOTE_PLACE_INFO_TYPE)
- {
- if (key.has("id"))
+ // Disable Save button because there is no item to save yet.
+ // The button will be enabled in onLandmarkLoaded callback.
+ mSaveBtn->setEnabled(FALSE);
+ }
+ else if (mPlaceInfoType == LANDMARK_INFO_TYPE)
{
- LLUUID parcel_id = key["id"].asUUID();
- mPlaceProfile->setParcelID(parcel_id);
+ mLandmarkInfo->setInfoType(LLPanelPlaceInfo::LANDMARK);
+
+ LLInventoryItem* item = gInventory.getItem(key["id"].asUUID());
+ if (!item)
+ return;
- // query the server to get the global 3D position of this
- // parcel - we need this for teleport/mapping functions.
- mRemoteParcelObserver->setParcelID(parcel_id);
+ setItem(item);
}
- else
+ else if (mPlaceInfoType == REMOTE_PLACE_INFO_TYPE)
{
- mPosGlobal = LLVector3d(key["x"].asReal(),
- key["y"].asReal(),
- key["z"].asReal());
- mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);
+ if (key.has("id"))
+ {
+ LLUUID parcel_id = key["id"].asUUID();
+ mPlaceProfile->setParcelID(parcel_id);
+
+ // query the server to get the global 3D position of this
+ // parcel - we need this for teleport/mapping functions.
+ mRemoteParcelObserver->setParcelID(parcel_id);
+ }
+ else
+ {
+ mPosGlobal = LLVector3d(key["x"].asReal(),
+ key["y"].asReal(),
+ key["z"].asReal());
+ mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);
+ }
+
+ mPlaceProfile->setInfoType(LLPanelPlaceInfo::PLACE);
}
+ else if (mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
+ {
+ S32 index = key["id"].asInteger();
- mPlaceProfile->setInfoType(LLPanelPlaceInfo::PLACE);
- }
- else if (mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
- {
- S32 index = key["id"].asInteger();
+ const LLTeleportHistoryStorage::slurl_list_t& hist_items =
+ LLTeleportHistoryStorage::getInstance()->getItems();
- const LLTeleportHistoryStorage::slurl_list_t& hist_items =
- LLTeleportHistoryStorage::getInstance()->getItems();
+ mPosGlobal = hist_items[index].mGlobalPos;
- mPosGlobal = hist_items[index].mGlobalPos;
+ mPlaceProfile->setInfoType(LLPanelPlaceInfo::TELEPORT_HISTORY);
+ mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);
+ }
- mPlaceProfile->setInfoType(LLPanelPlaceInfo::TELEPORT_HISTORY);
- mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);
+ updateVerbs();
}
- updateVerbs();
-
LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
if (!parcel_mgr)
return;
@@ -388,9 +391,12 @@ void LLPanelPlaces::onOpen(const LLSD& key)
{
parcel_mgr->removeObserver(mParcelObserver);
+ // Clear the reference to selection to allow its removal in deselectUnused().
+ mParcel.clear();
+
if (!parcel_mgr->selectionEmpty())
{
- parcel_mgr->deselectLand();
+ parcel_mgr->deselectUnused();
}
}
}
@@ -765,23 +771,23 @@ void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param)
mPickPanel->reshape(rect.getWidth(), rect.getHeight());
mPickPanel->setRect(rect);
}
- else if (item == "add_to_favbar")
- {
- if ( mItem.notNull() )
- {
- const LLUUID& favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
- if ( favorites_id.notNull() )
- {
- copy_inventory_item(gAgent.getID(),
- mItem->getPermissions().getOwner(),
- mItem->getUUID(),
- favorites_id,
- std::string(),
- LLPointer<LLInventoryCallback>(NULL));
- llinfos << "Copied inventory item #" << mItem->getUUID() << " to favorites." << llendl;
- }
- }
- }
+ else if (item == "add_to_favbar")
+ {
+ if ( mItem.notNull() )
+ {
+ const LLUUID& favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+ if ( favorites_id.notNull() )
+ {
+ copy_inventory_item(gAgent.getID(),
+ mItem->getPermissions().getOwner(),
+ mItem->getUUID(),
+ favorites_id,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ llinfos << "Copied inventory item #" << mItem->getUUID() << " to favorites." << llendl;
+ }
+ }
+ }
}
void LLPanelPlaces::onBackButtonClicked()
@@ -826,6 +832,14 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)
mLandmarkInfo->setVisible(FALSE);
}
+ else if (mPlaceInfoType == AGENT_INFO_TYPE)
+ {
+ LLViewerParcelMgr::getInstance()->removeObserver(mParcelObserver);
+
+ // Clear reference to parcel selection when closing place profile panel.
+ // LLViewerParcelMgr removes the selection if it has 1 reference to it.
+ mParcel.clear();
+ }
}
else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE ||
mPlaceInfoType == LANDMARK_INFO_TYPE)
@@ -858,6 +872,20 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)
}
}
+// virtual
+void LLPanelPlaces::handleVisibilityChange(BOOL new_visibility)
+{
+ LLPanel::handleVisibilityChange(new_visibility);
+
+ if (!new_visibility && mPlaceInfoType == AGENT_INFO_TYPE)
+ {
+ LLViewerParcelMgr::getInstance()->removeObserver(mParcelObserver);
+
+ // Clear reference to parcel selection when closing places panel.
+ mParcel.clear();
+ }
+}
+
void LLPanelPlaces::changedParcelSelection()
{
if (!mPlaceProfile)
diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h
index 27b5911ebb..0eba7f3afc 100644
--- a/indra/newview/llpanelplaces.h
+++ b/indra/newview/llpanelplaces.h
@@ -97,6 +97,8 @@ private:
void togglePickPanel(BOOL visible);
void togglePlaceInfoPanel(BOOL visible);
+ /*virtual*/ void handleVisibilityChange(BOOL new_visibility);
+
void updateVerbs();
LLPanelPlaceInfo* getCurrentInfoPanel();
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index b049f914ad..88b706fb6b 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -125,6 +125,8 @@ LLParticipantList::~LLParticipantList()
delete mParticipantListMenu;
mParticipantListMenu = NULL;
}
+
+ mAvatarList->setContextMenu(NULL);
}
void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible)
@@ -431,6 +433,10 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()
LLContextMenu* main_menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
"menu_participant_list.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
+ // Don't show sort options for P2P chat
+ bool is_sort_visible = (mParent.mAvatarList && mParent.mAvatarList->size() > 1);
+ main_menu->setItemVisible("SortByName", is_sort_visible);
+ main_menu->setItemVisible("SortByRecentSpeakers", is_sort_visible);
main_menu->setItemVisible("Moderator Options", isGroupModerator());
main_menu->arrangeAndClear();
@@ -456,11 +462,6 @@ void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const
LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteSelected", false);
LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteOthers", false);
}
-
- // Don't show sort options for P2P chat
- bool is_sort_visible = (mParent.mAvatarList && mParent.mAvatarList->size() > 1);
- LLMenuGL::sMenuContainer->childSetVisible("SortByName", is_sort_visible);
- LLMenuGL::sMenuContainer->childSetVisible("SortByRecentSpeakers", is_sort_visible);
}
void LLParticipantList::LLParticipantListMenu::sortParticipantList(const LLSD& userdata)
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index 0dd9203c6d..9608cd1263 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -44,7 +44,6 @@
#include "llvoavatar.h"
#include "llworld.h"
-const F32 SPEAKER_TIMEOUT = 10.f; // seconds of not being on voice channel before removed from list of active speakers
const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f);
const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f);
@@ -73,8 +72,6 @@ LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerTy
}
gVoiceClient->setUserVolume(id, LLMuteList::getInstance()->getSavedResidentVolume(id));
-
- mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
}
@@ -164,6 +161,89 @@ bool LLSortRecentSpeakers::operator()(const LLPointer<LLSpeaker> lhs, const LLPo
return( lhs->mDisplayName.compare(rhs->mDisplayName) < 0 );
}
+LLSpeakerActionTimer::LLSpeakerActionTimer(action_callback_t action_cb, F32 action_period, const LLUUID& speaker_id)
+: LLEventTimer(action_period)
+, mActionCallback(action_cb)
+, mSpeakerId(speaker_id)
+{
+}
+
+BOOL LLSpeakerActionTimer::tick()
+{
+ if (mActionCallback)
+ {
+ return (BOOL)mActionCallback(mSpeakerId);
+ }
+ return TRUE;
+}
+
+LLSpeakersDelayActionsStorage::LLSpeakersDelayActionsStorage(LLSpeakerActionTimer::action_callback_t action_cb, F32 action_delay)
+: mActionCallback(action_cb)
+, mActionDelay(action_delay)
+{
+}
+
+LLSpeakersDelayActionsStorage::~LLSpeakersDelayActionsStorage()
+{
+ removeAllTimers();
+}
+
+void LLSpeakersDelayActionsStorage::setActionTimer(const LLUUID& speaker_id)
+{
+ bool not_found = true;
+ if (mActionTimersMap.size() > 0)
+ {
+ not_found = mActionTimersMap.find(speaker_id) == mActionTimersMap.end();
+ }
+
+ // If there is already a started timer for the passed UUID don't do anything.
+ if (not_found)
+ {
+ // Starting a timer to remove an participant after delay is completed
+ mActionTimersMap.insert(LLSpeakerActionTimer::action_value_t(speaker_id,
+ new LLSpeakerActionTimer(
+ boost::bind(&LLSpeakersDelayActionsStorage::onTimerActionCallback, this, _1),
+ mActionDelay, speaker_id)));
+ }
+}
+
+void LLSpeakersDelayActionsStorage::unsetActionTimer(const LLUUID& speaker_id)
+{
+ if (mActionTimersMap.size() == 0) return;
+
+ LLSpeakerActionTimer::action_timer_iter_t it_speaker = mActionTimersMap.find(speaker_id);
+
+ if (it_speaker != mActionTimersMap.end())
+ {
+ delete it_speaker->second;
+ mActionTimersMap.erase(it_speaker);
+ }
+}
+
+void LLSpeakersDelayActionsStorage::removeAllTimers()
+{
+ LLSpeakerActionTimer::action_timer_iter_t iter = mActionTimersMap.begin();
+ for (; iter != mActionTimersMap.end(); ++iter)
+ {
+ delete iter->second;
+ }
+ mActionTimersMap.clear();
+}
+
+bool LLSpeakersDelayActionsStorage::onTimerActionCallback(const LLUUID& speaker_id)
+{
+ unsetActionTimer(speaker_id);
+
+ if (mActionCallback)
+ {
+ mActionCallback(speaker_id);
+ }
+
+ // do not return true to avoid deleting of an timer twice:
+ // in LLSpeakersDelayActionsStorage::unsetActionTimer() & LLEventTimer::updateClass()
+ return false;
+}
+
//
// LLSpeakerMgr
@@ -172,10 +252,14 @@ bool LLSortRecentSpeakers::operator()(const LLPointer<LLSpeaker> lhs, const LLPo
LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) :
mVoiceChannel(channelp)
{
+ static LLUICachedControl<F32> remove_delay ("SpeakerParticipantRemoveDelay", 10.0);
+
+ mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLSpeakerMgr::removeSpeaker, this, _1), remove_delay);
}
LLSpeakerMgr::~LLSpeakerMgr()
{
+ delete mSpeakerDelayRemover;
}
LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type)
@@ -198,7 +282,6 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin
{
// keep highest priority status (lowest value) instead of overriding current value
speakerp->mStatus = llmin(speakerp->mStatus, status);
- speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
// RN: due to a weird behavior where IMs from attached objects come from the wearer's agent_id
// we need to override speakers that we think are objects when we find out they are really
// residents
@@ -210,6 +293,8 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin
}
}
+ mSpeakerDelayRemover->unsetActionTimer(speakerp->mID);
+
return speakerp;
}
@@ -314,7 +399,7 @@ void LLSpeakerMgr::update(BOOL resort_ok)
S32 sort_index = 0;
speaker_list_t::iterator sorted_speaker_it;
for(sorted_speaker_it = mSpeakersSorted.begin();
- sorted_speaker_it != mSpeakersSorted.end(); )
+ sorted_speaker_it != mSpeakersSorted.end(); ++sorted_speaker_it)
{
LLPointer<LLSpeaker> speakerp = *sorted_speaker_it;
@@ -327,19 +412,6 @@ void LLSpeakerMgr::update(BOOL resort_ok)
// stuff sort ordinal into speaker so the ui can sort by this value
speakerp->mSortIndex = sort_index++;
-
- // remove speakers that have been gone too long
- if (speakerp->mStatus == LLSpeaker::STATUS_NOT_IN_CHANNEL && speakerp->mActivityTimer.hasExpired())
- {
- fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "remove");
-
- mSpeakers.erase(speakerp->mID);
- sorted_speaker_it = mSpeakersSorted.erase(sorted_speaker_it);
- }
- else
- {
- ++sorted_speaker_it;
- }
}
}
@@ -363,6 +435,35 @@ void LLSpeakerMgr::updateSpeakerList()
}
}
+void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp)
+{
+ speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+ speakerp->mDotColor = INACTIVE_COLOR;
+ mSpeakerDelayRemover->setActionTimer(speakerp->mID);
+}
+
+bool LLSpeakerMgr::removeSpeaker(const LLUUID& speaker_id)
+{
+ mSpeakers.erase(speaker_id);
+
+ speaker_list_t::iterator sorted_speaker_it = mSpeakersSorted.begin();
+
+ for(; sorted_speaker_it != mSpeakersSorted.end(); ++sorted_speaker_it)
+ {
+ if (speaker_id == (*sorted_speaker_it)->mID)
+ {
+ mSpeakersSorted.erase(sorted_speaker_it);
+ break;
+ }
+ }
+
+ fireEvent(new LLSpeakerListChangeEvent(this, speaker_id), "remove");
+
+ update(TRUE);
+
+ return false;
+}
+
LLPointer<LLSpeaker> LLSpeakerMgr::findSpeaker(const LLUUID& speaker_id)
{
//In some conditions map causes crash if it is empty(Windows only), adding check (EK)
@@ -511,9 +612,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
{
if (agent_data["transition"].asString() == "LEAVE" && speakerp.notNull())
{
- speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
- speakerp->mDotColor = INACTIVE_COLOR;
- speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+ setSpeakerNotInChannel(speakerp);
}
else if (agent_data["transition"].asString() == "ENTER")
{
@@ -563,9 +662,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
std::string agent_transition = update_it->second.asString();
if (agent_transition == "LEAVE" && speakerp.notNull())
{
- speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
- speakerp->mDotColor = INACTIVE_COLOR;
- speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+ setSpeakerNotInChannel(speakerp);
}
else if ( agent_transition == "ENTER")
{
@@ -734,12 +831,13 @@ void LLActiveSpeakerMgr::updateSpeakerList()
mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
// always populate from active voice channel
- if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel)
+ if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel) //MA: seems this is always false
{
fireEvent(new LLSpeakerListChangeEvent(this, LLUUID::null), "clear");
mSpeakers.clear();
mSpeakersSorted.clear();
mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
+ mSpeakerDelayRemover->removeAllTimers();
}
LLSpeakerMgr::updateSpeakerList();
@@ -800,9 +898,7 @@ void LLLocalSpeakerMgr::updateSpeakerList()
LLVOAvatar* avatarp = (LLVOAvatar*)gObjectList.findObject(speaker_id);
if (!avatarp || dist_vec(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS)
{
- speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
- speakerp->mDotColor = INACTIVE_COLOR;
- speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+ setSpeakerNotInChannel(speakerp);
}
}
}
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
index da8dfdf548..63237204c8 100644
--- a/indra/newview/llspeakers.h
+++ b/indra/newview/llspeakers.h
@@ -73,7 +73,6 @@ public:
F32 mLastSpokeTime; // timestamp when this speaker last spoke
F32 mSpeechVolume; // current speech amplitude (timea average rms amplitude?)
std::string mDisplayName; // cache user name for this speaker
- LLFrameTimer mActivityTimer; // time out speakers when they are not part of current voice channel
BOOL mHasSpoken; // has this speaker said anything this session?
BOOL mHasLeftCurrentCall; // has this speaker left the current voice call?
LLColor4 mDotColor;
@@ -120,6 +119,92 @@ private:
const LLUUID& mSpeakerID;
};
+/**
+ * class LLSpeakerActionTimer
+ *
+ * Implements a timer that calls stored callback action for stored speaker after passed period.
+ *
+ * Action is called until callback returns "true".
+ * In this case the timer will be removed via LLEventTimer::updateClass().
+ * Otherwise it should be deleted manually in place where it is used.
+ * If action callback is not set timer will tick only once and deleted.
+ */
+class LLSpeakerActionTimer : public LLEventTimer
+{
+public:
+ typedef boost::function<bool(const LLUUID&)> action_callback_t;
+ typedef std::map<LLUUID, LLSpeakerActionTimer*> action_timers_map_t;
+ typedef action_timers_map_t::value_type action_value_t;
+ typedef action_timers_map_t::const_iterator action_timer_const_iter_t;
+ typedef action_timers_map_t::iterator action_timer_iter_t;
+
+ /**
+ * Constructor.
+ *
+ * @param action_cb - callback which will be called each time after passed action period.
+ * @param action_period - time in seconds timer should tick.
+ * @param speaker_id - LLUUID of speaker which will be passed into action callback.
+ */
+ LLSpeakerActionTimer(action_callback_t action_cb, F32 action_period, const LLUUID& speaker_id);
+ virtual ~LLSpeakerActionTimer() {};
+
+ /**
+ * Implements timer "tick".
+ *
+ * If action callback is not specified returns true. Instance will be deleted by LLEventTimer::updateClass().
+ */
+ virtual BOOL tick();
+
+private:
+ action_callback_t mActionCallback;
+ LLUUID mSpeakerId;
+};
+
+/**
+ * Represents a functionality to store actions for speakers with delay.
+ * Is based on LLSpeakerActionTimer.
+ */
+class LLSpeakersDelayActionsStorage
+{
+public:
+ LLSpeakersDelayActionsStorage(LLSpeakerActionTimer::action_callback_t action_cb, F32 action_delay);
+ ~LLSpeakersDelayActionsStorage();
+
+ /**
+ * Sets new LLSpeakerActionTimer with passed speaker UUID.
+ */
+ void setActionTimer(const LLUUID& speaker_id);
+
+ /**
+ * Removes stored LLSpeakerActionTimer for passed speaker UUID from internal map and deletes it.
+ *
+ * @see onTimerActionCallback()
+ */
+ void unsetActionTimer(const LLUUID& speaker_id);
+
+ void removeAllTimers();
+private:
+ /**
+ * Callback of the each instance of LLSpeakerActionTimer.
+ *
+ * Unsets an appropriate timer instance and calls action callback for specified speacker_id.
+ * It always returns false to not use LLEventTimer::updateClass functionality of timer deleting.
+ *
+ * @see unsetActionTimer()
+ */
+ bool onTimerActionCallback(const LLUUID& speaker_id);
+
+ LLSpeakerActionTimer::action_timers_map_t mActionTimersMap;
+ LLSpeakerActionTimer::action_callback_t mActionCallback;
+
+ /**
+ * Delay to call action callback for speakers after timer was set.
+ */
+ F32 mActionDelay;
+
+};
+
+
class LLSpeakerMgr : public LLOldEvents::LLObservable
{
public:
@@ -144,6 +229,8 @@ public:
protected:
virtual void updateSpeakerList();
+ void setSpeakerNotInChannel(LLSpeaker* speackerp);
+ bool removeSpeaker(const LLUUID& speaker_id);
typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t;
speaker_map_t mSpeakers;
@@ -151,6 +238,11 @@ protected:
speaker_list_t mSpeakersSorted;
LLFrameTimer mSpeechTimer;
LLVoiceChannel* mVoiceChannel;
+
+ /**
+ * time out speakers when they are not part of current session
+ */
+ LLSpeakersDelayActionsStorage* mSpeakerDelayRemover;
};
class LLIMSpeakerMgr : public LLSpeakerMgr
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 9c4825763b..2b846d33fc 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -1103,7 +1103,10 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op)
{
if (op == TEXTURE_CANCEL)
mViewModel->resetDirty();
- else
+ // If the "no_commit_on_selection" parameter is set
+ // we get dirty only when user presses OK in the picker
+ // (i.e. op == TEXTURE_SELECT) or texture changes via DnD.
+ else if (mCommitOnSelection || op == TEXTURE_SELECT)
mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
if( floaterp->isDirty() )
@@ -1125,7 +1128,7 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op)
{
// If the "no_commit_on_selection" parameter is set
// we commit only when user presses OK in the picker
- // (i.e. op == TEXTURE_SELECT) or changes texture via DnD.
+ // (i.e. op == TEXTURE_SELECT) or texture changes via DnD.
if (mCommitOnSelection || op == TEXTURE_SELECT)
onCommit();
}
@@ -1165,6 +1168,9 @@ BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask,
{
if(doDrop(item))
{
+ if (!mCommitOnSelection)
+ mViewModel->setDirty();
+
// This removes the 'Multiple' overlay, since
// there is now only one texture selected.
setTentative( FALSE );
diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h
index 023329a9b2..8ca92c3d87 100644
--- a/indra/newview/lltexturectrl.h
+++ b/indra/newview/lltexturectrl.h
@@ -74,7 +74,8 @@ public:
Optional<std::string> default_image_name;
Optional<bool> allow_no_texture;
Optional<bool> can_apply_immediately;
- Optional<bool> no_commit_on_selection; // don't commit unless it's DnD or OK button press
+ Optional<bool> no_commit_on_selection; // alternative mode: commit occurs and the widget gets dirty
+ // only on DnD or when OK is pressed in the picker
Optional<S32> label_width;
Optional<LLUIColor> border_color;
diff --git a/indra/newview/lltransientdockablefloater.cpp b/indra/newview/lltransientdockablefloater.cpp
index 7e4d4988d1..c9bfe178ce 100644
--- a/indra/newview/lltransientdockablefloater.cpp
+++ b/indra/newview/lltransientdockablefloater.cpp
@@ -42,6 +42,7 @@ LLTransientDockableFloater::LLTransientDockableFloater(LLDockControl* dockContro
LLDockableFloater(dockControl, uniqueDocking, key, params)
{
LLTransientFloaterMgr::getInstance()->registerTransientFloater(this);
+ LLTransientFloater::init(this);
}
LLTransientDockableFloater::~LLTransientDockableFloater()
diff --git a/indra/newview/lltransientdockablefloater.h b/indra/newview/lltransientdockablefloater.h
index 6e8a3afd22..e0541d6597 100644
--- a/indra/newview/lltransientdockablefloater.h
+++ b/indra/newview/lltransientdockablefloater.h
@@ -37,12 +37,13 @@
#include "llfloater.h"
#include "lldockcontrol.h"
#include "lldockablefloater.h"
+#include "lltransientfloatermgr.h"
/**
* Represents floater that can dock and managed by transient floater manager.
* Transient floaters should be hidden if user click anywhere except defined view list.
*/
-class LLTransientDockableFloater : public LLDockableFloater
+class LLTransientDockableFloater : public LLDockableFloater, LLTransientFloater
{
public:
LOG_CLASS(LLTransientDockableFloater);
@@ -52,6 +53,7 @@ public:
/*virtual*/ void setVisible(BOOL visible);
/* virtual */void setDocked(bool docked, bool pop_on_undock = true);
+ virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::GLOBAL; }
};
#endif /* LL_TRANSIENTDOCKABLEFLOATER_H */
diff --git a/indra/newview/lltransientfloatermgr.cpp b/indra/newview/lltransientfloatermgr.cpp
index 347399f239..8f1a738453 100644
--- a/indra/newview/lltransientfloatermgr.cpp
+++ b/indra/newview/lltransientfloatermgr.cpp
@@ -44,57 +44,68 @@ LLTransientFloaterMgr::LLTransientFloaterMgr()
{
gViewerWindow->getRootView()->addMouseDownCallback(boost::bind(
&LLTransientFloaterMgr::leftMouseClickCallback, this, _1, _2, _3));
+
+ mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(GLOBAL, std::set<LLView*>()));
+ mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(IM, std::set<LLView*>()));
}
-void LLTransientFloaterMgr::registerTransientFloater(LLFloater* floater)
+void LLTransientFloaterMgr::registerTransientFloater(LLTransientFloater* floater)
{
mTransSet.insert(floater);
}
-void LLTransientFloaterMgr::unregisterTransientFloater(LLFloater* floater)
+void LLTransientFloaterMgr::unregisterTransientFloater(LLTransientFloater* floater)
{
mTransSet.erase(floater);
}
+void LLTransientFloaterMgr::addControlView(ETransientGroup group, LLView* view)
+{
+ mGroupControls.find(group)->second.insert(view);
+}
+
+void LLTransientFloaterMgr::removeControlView(ETransientGroup group, LLView* view)
+{
+ mGroupControls.find(group)->second.erase(view);
+}
+
void LLTransientFloaterMgr::addControlView(LLView* view)
{
- mControlsSet.insert(view);
+ addControlView(GLOBAL, view);
}
void LLTransientFloaterMgr::removeControlView(LLView* view)
{
// we will still get focus lost callbacks on this view, but that's ok
// since we run sanity checking logic every time
- mControlsSet.erase(view);
+ removeControlView(GLOBAL, view);
}
-void LLTransientFloaterMgr::hideTransientFloaters()
+void LLTransientFloaterMgr::hideTransientFloaters(S32 x, S32 y)
{
- for (std::set<LLFloater*>::iterator it = mTransSet.begin(); it
+ for (std::set<LLTransientFloater*>::iterator it = mTransSet.begin(); it
!= mTransSet.end(); it++)
{
- LLFloater* floater = *it;
- if (floater->isDocked())
+ LLTransientFloater* floater = *it;
+ if (floater->isTransientDocked())
{
- floater->setVisible(FALSE);
+ ETransientGroup group = floater->getGroup();
+
+ bool hide = isControlClicked(mGroupControls.find(group)->second, x, y);
+ if (hide)
+ {
+ floater->setTransientVisible(FALSE);
+ }
}
}
}
-void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,
- MASK mask)
+bool LLTransientFloaterMgr::isControlClicked(std::set<LLView*>& set, S32 x, S32 y)
{
- bool hide = true;
- for (controls_set_t::iterator it = mControlsSet.begin(); it
- != mControlsSet.end(); it++)
+ bool res = true;
+ for (controls_set_t::iterator it = set.begin(); it
+ != set.end(); it++)
{
- // don't hide transient floater if any context menu opened
- if (LLMenuGL::sMenuContainer->getVisibleMenu() != NULL)
- {
- hide = false;
- break;
- }
-
LLView* control_view = *it;
if (!control_view->getVisible())
{
@@ -105,14 +116,32 @@ void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,
// if click inside view rect
if (rect.pointInRect(x, y))
{
- hide = false;
+ res = false;
break;
}
}
+ return res;
+}
+
+void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,
+ MASK mask)
+{
+ // don't hide transient floater if any context menu opened
+ if (LLMenuGL::sMenuContainer->getVisibleMenu() != NULL)
+ {
+ return;
+ }
+ bool hide = isControlClicked(mGroupControls.find(GLOBAL)->second, x, y);
if (hide)
{
- hideTransientFloaters();
+ hideTransientFloaters(x, y);
}
}
+void LLTransientFloater::init(LLFloater* thiz)
+{
+ // used since LLTransientFloater(this) can't be used in descendant constructor parameter initialization.
+ mFloater = thiz;
+}
+
diff --git a/indra/newview/lltransientfloatermgr.h b/indra/newview/lltransientfloatermgr.h
index cef6e1fe45..1f99325a7f 100644
--- a/indra/newview/lltransientfloatermgr.h
+++ b/indra/newview/lltransientfloatermgr.h
@@ -37,27 +37,60 @@
#include "llsingleton.h"
#include "llfloater.h"
+class LLTransientFloater;
/**
* Provides functionality to hide transient floaters.
*/
class LLTransientFloaterMgr: public LLSingleton<LLTransientFloaterMgr>
{
-public:
+protected:
LLTransientFloaterMgr();
- void registerTransientFloater(LLFloater* floater);
- void unregisterTransientFloater(LLFloater* floater);
+ friend class LLSingleton<LLTransientFloaterMgr>;
+
+public:
+ enum ETransientGroup
+ {
+ GLOBAL, IM
+ };
+
+ void registerTransientFloater(LLTransientFloater* floater);
+ void unregisterTransientFloater(LLTransientFloater* floater);
+ void addControlView(ETransientGroup group, LLView* view);
+ void removeControlView(ETransientGroup group, LLView* view);
void addControlView(LLView* view);
void removeControlView(LLView* view);
private:
- void hideTransientFloaters();
+ void hideTransientFloaters(S32 x, S32 y);
void leftMouseClickCallback(S32 x, S32 y, MASK mask);
-
+ bool isControlClicked(std::set<LLView*>& set, S32 x, S32 y);
private:
- std::set<LLFloater*> mTransSet;
+ std::set<LLTransientFloater*> mTransSet;
+
typedef std::set<LLView*> controls_set_t;
- controls_set_t mControlsSet;
+ typedef std::map<ETransientGroup, std::set<LLView*> > group_controls_t;
+ group_controls_t mGroupControls;
+};
+
+/**
+ * An abstract class declares transient floater interfaces.
+ */
+class LLTransientFloater
+{
+protected:
+ /**
+ * Class initialization method.
+ * Should be called from descendant constructor.
+ */
+ void init(LLFloater* thiz);
+public:
+ virtual LLTransientFloaterMgr::ETransientGroup getGroup() = 0;
+ bool isTransientDocked() { return mFloater->isDocked(); };
+ void setTransientVisible(BOOL visible) {mFloater->setVisible(visible); }
+
+private:
+ LLFloater* mFloater;
};
#endif // LL_LLTRANSIENTFLOATERMGR_H
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 7487fa9997..0358efc0af 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1472,7 +1472,12 @@ void inventory_offer_handler(LLOfferInfo* info)
{
LLStringUtil::truncate(msg, indx);
}
-
+
+ if(LLAssetType::AT_LANDMARK == info->mType)
+ {
+ msg = LLViewerInventoryItem::getDisplayName(msg);
+ }
+
LLSD args;
args["[OBJECTNAME]"] = msg;
diff --git a/indra/newview/skins/default/xui/en/favorites_bar_button.xml b/indra/newview/skins/default/xui/en/favorites_bar_button.xml
index 6adf2a5950..b365040c20 100644
--- a/indra/newview/skins/default/xui/en/favorites_bar_button.xml
+++ b/indra/newview/skins/default/xui/en/favorites_bar_button.xml
@@ -10,6 +10,8 @@
image_selected="transparent.j2c"
image_unselected="transparent.j2c"
image_pressed="Favorite_Link_Over"
+ image_hover_selected="Favorite_Link_Over"
+ image_hover_unselected="Favorite_Link_Over"
hover_glow_amount="0.15"
label_shadow="false"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml
index 1d51d19a4a..bd25288a9e 100644
--- a/indra/newview/skins/default/xui/en/floater_im_container.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_container.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<multi_floater
- can_minimize="false"
+ can_close="false"
+ can_minimize="true"
can_resize="true"
height="390"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
index d3db9fd531..09ec2137b7 100644
--- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml
+++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
@@ -416,7 +416,6 @@ image_pressed_selected "Lit" + "Selected" - there are new messages and the Well
name="Unread"
image_overlay="Notices_Unread"
image_overlay_alignment="center"
- pad_right="15"
tool_tip="Notifications"
width="34" >
<button.init_callback
diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
index 673052c3b5..0893c204e7 100644
--- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
@@ -67,6 +67,7 @@ background_visible="true"
layout="topleft"
left="20"
name="insignia"
+ no_commit_on_selection="true"
tool_tip="Click to choose a picture"
top_pad="5"
width="100" />
diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml
index 6b3fb04549..618d2f3b8e 100644
--- a/indra/newview/skins/default/xui/en/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml
@@ -49,6 +49,18 @@
Select multiple Members by holding the Ctrl key and
clicking on their names.
</panel.string>
+ <panel.string
+ name="power_folder_icon">
+ Inv_FolderClosed
+ </panel.string>
+ <panel.string
+ name="power_all_have_icon">
+ Checkbox_On
+ </panel.string>
+ <panel.string
+ name="power_partial_icon">
+ Checkbox_Off
+ </panel.string>
<filter_editor
layout="topleft"
top="5"
@@ -310,7 +322,7 @@ things in this group. There&apos;s a broad variety of Abilities.
width="285">
Allowed Abilities
</text>
- <scroll_list
+ <scroll_list
draw_stripes="true"
height="90"
layout="topleft"
@@ -322,8 +334,16 @@ things in this group. There&apos;s a broad variety of Abilities.
width="300">
<scroll_list.columns
label=""
+ name="icon"
+ width="2" />
+ <scroll_list.columns
+ label=""
+ name="checkbox"
+ width="20" />
+ <scroll_list.columns
+ label=""
name="action"
- width="300" />
+ width="270" />
</scroll_list>
</panel>
<panel
diff --git a/indra/newview/skins/default/xui/en/panel_my_profile.xml b/indra/newview/skins/default/xui/en/panel_my_profile.xml
index 34cde61252..4894ae01da 100644
--- a/indra/newview/skins/default/xui/en/panel_my_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_my_profile.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
- height="535"
+ height="500"
label="Profile"
layout="topleft"
left="0"
@@ -41,7 +41,7 @@
layout="topleft"
left="0"
top="0"
- height="535"
+ height="480"
width="313"
border_size="0">
<layout_panel
@@ -50,7 +50,7 @@
layout="topleft"
top="0"
left="0"
- height="505"
+ height="480"
user_resize="false"
width="313">
<scroll_container
@@ -60,7 +60,7 @@
left="0"
name="profile_scroll"
opaque="true"
- height="505"
+ height="480"
width="313"
top="0">
<panel
@@ -374,8 +374,9 @@
follows="bottom|right"
height="23"
left="20"
- top="0"
+ top="5"
label="Edit Profile"
+ layout="topleft"
name="edit_profile_btn"
tool_tip="Edit your personal information"
width="130" />
@@ -384,7 +385,9 @@
height="23"
label="Edit Appearance"
left_pad="10"
+ layout="topleft"
name="edit_appearance_btn"
+ top="5"
tool_tip="Create/edit your appearance: physical data, clothes and etc."
width="130" />
</layout_panel>