summaryrefslogtreecommitdiff
path: root/indra/newview/llavatarlist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llavatarlist.cpp')
-rw-r--r--indra/newview/llavatarlist.cpp229
1 files changed, 211 insertions, 18 deletions
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index 3a07c6e5ef..6ec62a61a0 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -33,18 +33,59 @@
#include "llviewerprecompiledheaders.h"
#include "llavatarlist.h"
+#include "llagentdata.h" // for comparator
// newview
#include "llcallingcard.h" // for LLAvatarTracker
#include "llcachename.h"
+#include "llrecentpeople.h"
#include "llvoiceclient.h"
+#include "llviewercontrol.h" // for gSavedSettings
static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list");
+// Last interaction time update period.
+static const F32 LIT_UPDATE_PERIOD = 5;
+
// Maximum number of avatars that can be added to a list in one pass.
// Used to limit time spent for avatar list update per frame.
static const unsigned ADD_LIMIT = 50;
+bool LLAvatarList::contains(const LLUUID& id)
+{
+ const uuid_vector_t& ids = getIDs();
+ return std::find(ids.begin(), ids.end(), id) != ids.end();
+}
+
+void LLAvatarList::toggleIcons()
+{
+ // Save the new value for new items to use.
+ mShowIcons = !mShowIcons;
+ gSavedSettings.setBOOL(mIconParamName, mShowIcons);
+
+ // Show/hide icons for all existing items.
+ std::vector<LLPanel*> items;
+ getItems(items);
+ for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
+ {
+ static_cast<LLAvatarListItem*>(*it)->setAvatarIconVisible(mShowIcons);
+ }
+}
+
+void LLAvatarList::setSpeakingIndicatorsVisible(bool visible)
+{
+ // Save the new value for new items to use.
+ mShowSpeakingIndicator = visible;
+
+ // Show/hide icons for all existing items.
+ std::vector<LLPanel*> items;
+ getItems(items);
+ for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
+ {
+ static_cast<LLAvatarListItem*>(*it)->showSpeakingIndicator(mShowSpeakingIndicator);
+ }
+}
+
static bool findInsensitive(std::string haystack, const std::string& needle_upper)
{
LLStringUtil::toUpper(haystack);
@@ -58,28 +99,73 @@ static const LLFlatListView::ItemReverseComparator REVERSE_NAME_COMPARATOR(NAME_
LLAvatarList::Params::Params()
: ignore_online_status("ignore_online_status", false)
+, show_last_interaction_time("show_last_interaction_time", false)
+, show_info_btn("show_info_btn", true)
+, show_profile_btn("show_profile_btn", true)
+, show_speaking_indicator("show_speaking_indicator", true)
{
}
LLAvatarList::LLAvatarList(const Params& p)
: LLFlatListView(p)
, mIgnoreOnlineStatus(p.ignore_online_status)
+, mShowLastInteractionTime(p.show_last_interaction_time)
, mContextMenu(NULL)
, mDirty(true) // to force initial update
+, mLITUpdateTimer(NULL)
+, mShowIcons(true)
+, mShowInfoBtn(p.show_info_btn)
+, mShowProfileBtn(p.show_profile_btn)
+, mShowSpeakingIndicator(p.show_speaking_indicator)
{
setCommitOnSelectionChange(true);
// Set default sort order.
setComparator(&NAME_COMPARATOR);
+
+ if (mShowLastInteractionTime)
+ {
+ mLITUpdateTimer = new LLTimer();
+ mLITUpdateTimer->setTimerExpirySec(0); // zero to force initial update
+ mLITUpdateTimer->start();
+ }
+}
+
+LLAvatarList::~LLAvatarList()
+{
+ delete mLITUpdateTimer;
+}
+
+void LLAvatarList::setShowIcons(std::string param_name)
+{
+ mIconParamName= param_name;
+ mShowIcons = gSavedSettings.getBOOL(mIconParamName);
}
// virtual
void LLAvatarList::draw()
{
+ // *NOTE dzaporozhan
+ // Call refresh() after draw() to avoid flickering of avatar list items.
+
+ LLFlatListView::draw();
+
if (mDirty)
refresh();
- LLFlatListView::draw();
+ if (mShowLastInteractionTime && mLITUpdateTimer->hasExpired())
+ {
+ updateLastInteractionTimes();
+ mLITUpdateTimer->setTimerExpirySec(LIT_UPDATE_PERIOD); // restart the timer
+ }
+}
+
+//virtual
+void LLAvatarList::clear()
+{
+ getIDs().clear();
+ setDirty(true);
+ LLFlatListView::clear();
}
void LLAvatarList::setNameFilter(const std::string& filter)
@@ -97,6 +183,15 @@ void LLAvatarList::sortByName()
sort();
}
+void LLAvatarList::setDirty(bool val /*= true*/, bool force_refresh /*= false*/)
+{
+ mDirty = val;
+ if(mDirty && force_refresh)
+ {
+ refresh();
+ }
+}
+
//////////////////////////////////////////////////////////////////////////
// PROTECTED SECTION
//////////////////////////////////////////////////////////////////////////
@@ -109,17 +204,17 @@ void LLAvatarList::refresh()
bool have_filter = !mNameFilter.empty();
// Save selection.
- std::vector<LLUUID> selected_ids;
+ uuid_vec_t selected_ids;
getSelectedUUIDs(selected_ids);
LLUUID current_id = getSelectedUUID();
// Determine what to add and what to remove.
- std::vector<LLUUID> added, removed;
+ uuid_vec_t added, removed;
LLAvatarList::computeDifference(getIDs(), added, removed);
// Handle added items.
unsigned nadded = 0;
- for (std::vector<LLUUID>::const_iterator it=added.begin(); it != added.end(); it++)
+ for (uuid_vec_t::const_iterator it=added.begin(); it != added.end(); it++)
{
std::string name;
const LLUUID& buddy_id = *it;
@@ -141,7 +236,7 @@ void LLAvatarList::refresh()
}
// Handle removed items.
- for (std::vector<LLUUID>::const_iterator it=removed.begin(); it != removed.end(); it++)
+ for (uuid_vec_t::const_iterator it=removed.begin(); it != removed.end(); it++)
{
removeItemByUUID(*it);
modified = true;
@@ -184,24 +279,86 @@ void LLAvatarList::refresh()
bool dirty = add_limit_exceeded || (have_filter && !have_names);
setDirty(dirty);
+ // Refreshed all items.
+ if(!dirty)
+ {
+ // Highlight items matching the filter.
+ std::vector<LLPanel*> items;
+ getItems(items);
+ for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
+ {
+ static_cast<LLAvatarListItem*>(*it)->setHighlight(mNameFilter);
+ }
+
+ // Send refresh_complete signal.
+ std::vector<LLSD> cur_values;
+ getValues(cur_values);
+ mRefreshCompleteSignal(this, LLSD((S32)cur_values.size()));
+ }
+
// Commit if we've added/removed items.
if (modified)
onCommit();
}
+bool LLAvatarList::filterHasMatches()
+{
+ uuid_vector_t values = getIDs();
+
+ for (uuid_vector_t::const_iterator it=values.begin(); it != values.end(); it++)
+ {
+ std::string name;
+ const LLUUID& buddy_id = *it;
+ BOOL have_name = gCacheName->getFullName(buddy_id, name);
+
+ // If name has not been loaded yet we consider it as a match.
+ // When the name will be loaded the filter will be applied again(in refresh()).
+
+ if (have_name && !findInsensitive(name, mNameFilter))
+ {
+ continue;
+ }
+
+ return true;
+ }
+ return false;
+}
+
+boost::signals2::connection LLAvatarList::setRefreshCompleteCallback(const commit_signal_t::slot_type& cb)
+{
+ return mRefreshCompleteSignal.connect(cb);
+}
+
+boost::signals2::connection LLAvatarList::setItemDoubleClickCallback(const mouse_signal_t::slot_type& cb)
+{
+ return mItemDoubleClickSignal.connect(cb);
+}
+
+//virtual
+S32 LLAvatarList::notifyParent(const LLSD& info)
+{
+ if (info.has("sort") && &NAME_COMPARATOR == mItemComparator)
+ {
+ sort();
+ return 1;
+ }
+ return LLFlatListView::notifyParent(info);
+}
void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos)
{
LLAvatarListItem* item = new LLAvatarListItem();
- item->showStatus(false);
- item->showInfoBtn(true);
- item->showSpeakingIndicator(true);
item->setName(name);
- item->setAvatarId(id, mIgnoreOnlineStatus);
+ item->setAvatarId(id, mSessionID, mIgnoreOnlineStatus);
item->setOnline(mIgnoreOnlineStatus ? true : is_online);
- item->setContextMenu(mContextMenu);
+ item->showLastInteractionTime(mShowLastInteractionTime);
+
+ item->setAvatarIconVisible(mShowIcons);
+ item->setShowInfoBtn(mShowInfoBtn);
+ item->setShowProfileBtn(mShowProfileBtn);
+ item->showSpeakingIndicator(mShowSpeakingIndicator);
- item->childSetVisible("info_btn", false);
+ item->setDoubleClickCallback(boost::bind(&LLAvatarList::onItemDoucleClicked, this, _1, _2, _3, _4));
addItem(item, id, pos);
}
@@ -212,7 +369,7 @@ BOOL LLAvatarList::handleRightMouseDown(S32 x, S32 y, MASK mask)
BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask);
if ( mContextMenu )
{
- std::vector<LLUUID> selected_uuids;
+ uuid_vec_t selected_uuids;
getSelectedUUIDs(selected_uuids);
mContextMenu->show(this, selected_uuids, x, y);
}
@@ -220,12 +377,12 @@ BOOL LLAvatarList::handleRightMouseDown(S32 x, S32 y, MASK mask)
}
void LLAvatarList::computeDifference(
- const std::vector<LLUUID>& vnew_unsorted,
- std::vector<LLUUID>& vadded,
- std::vector<LLUUID>& vremoved)
+ const uuid_vec_t& vnew_unsorted,
+ uuid_vec_t& vadded,
+ uuid_vec_t& vremoved)
{
- std::vector<LLUUID> vcur;
- std::vector<LLUUID> vnew = vnew_unsorted;
+ uuid_vec_t vcur;
+ uuid_vec_t vnew = vnew_unsorted;
// Convert LLSDs to LLUUIDs.
{
@@ -239,7 +396,7 @@ void LLAvatarList::computeDifference(
std::sort(vcur.begin(), vcur.end());
std::sort(vnew.begin(), vnew.end());
- std::vector<LLUUID>::iterator it;
+ uuid_vec_t::iterator it;
size_t maxsize = llmax(vcur.size(), vnew.size());
vadded.resize(maxsize);
vremoved.resize(maxsize);
@@ -253,6 +410,28 @@ void LLAvatarList::computeDifference(
vadded.erase(it, vadded.end());
}
+// Refresh shown time of our last interaction with all listed avatars.
+void LLAvatarList::updateLastInteractionTimes()
+{
+ S32 now = (S32) LLDate::now().secondsSinceEpoch();
+ std::vector<LLPanel*> items;
+ getItems(items);
+
+ for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
+ {
+ // *TODO: error handling
+ LLAvatarListItem* item = static_cast<LLAvatarListItem*>(*it);
+ S32 secs_since = now - (S32) LLRecentPeople::instance().getDate(item->getAvatarId()).secondsSinceEpoch();
+ if (secs_since >= 0)
+ item->setLastInteractionTime(secs_since);
+ }
+}
+
+void LLAvatarList::onItemDoucleClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask)
+{
+ mItemDoubleClickSignal(ctrl, x, y, mask);
+}
+
bool LLAvatarItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const
{
const LLAvatarListItem* avatar_item1 = dynamic_cast<const LLAvatarListItem*>(item1);
@@ -277,3 +456,17 @@ bool LLAvatarItemNameComparator::doCompare(const LLAvatarListItem* avatar_item1,
return name1 < name2;
}
+bool LLAvatarItemAgentOnTopComparator::doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const
+{
+ //keep agent on top, if first is agent,
+ //then we need to return true to elevate this id, otherwise false.
+ if(avatar_item1->getAvatarId() == gAgentID)
+ {
+ return true;
+ }
+ else if (avatar_item2->getAvatarId() == gAgentID)
+ {
+ return false;
+ }
+ return LLAvatarItemNameComparator::doCompare(avatar_item1,avatar_item2);
+}