phoenix-firestorm/indra/newview/llblocklist.cpp

477 lines
12 KiB
C++

/**
* @file llblocklist.cpp
* @brief List of the blocked avatars and objects.
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llblocklist.h"
#include "llavataractions.h"
#include "llblockedlistitem.h"
#include "llfloatersidepanelcontainer.h"
#include "llviewermenu.h"
static LLDefaultChildRegistry::Register<LLBlockList> r("block_list");
static const LLBlockListNameComparator NAME_COMPARATOR;
static const LLBlockListNameTypeComparator NAME_TYPE_COMPARATOR;
LLBlockList::LLBlockList(const Params& p)
: LLFlatListViewEx(p),
mDirty(true),
mShouldAddAll(true),
mActionType(NONE),
mMuteListSize(0)
{
LLMuteList::getInstance()->addObserver(this);
mMuteListSize = LLMuteList::getInstance()->getMutes().size();
// Set up context menu.
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
registrar.add ("Block.Action", boost::bind(&LLBlockList::onCustomAction, this, _2));
enable_registrar.add("Block.Enable", boost::bind(&LLBlockList::isActionEnabled, this, _2));
enable_registrar.add("Block.Check", boost::bind(&LLBlockList::isMenuItemChecked, this, _2));
enable_registrar.add("Block.Visible", boost::bind(&LLBlockList::isMenuItemVisible, this, _2));
LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
"menu_people_blocked_gear.xml",
gMenuHolder,
LLViewerMenuHolderGL::child_registry_t::instance());
if(context_menu)
{
mContextMenu = context_menu->getHandle();
}
}
LLBlockList::~LLBlockList()
{
if (mContextMenu.get())
{
mContextMenu.get()->die();
}
LLMuteList::getInstance()->removeObserver(this);
}
void LLBlockList::createList()
{
std::vector<LLMute> mutes = LLMuteList::instance().getMutes();
std::vector<LLMute>::const_iterator mute_it = mutes.begin();
for (; mute_it != mutes.end(); ++mute_it)
{
addNewItem(&*mute_it);
}
}
BlockListActionType LLBlockList::getCurrentMuteListActionType()
{
BlockListActionType type = NONE;
U32 curSize = LLMuteList::getInstance()->getMutes().size();
if( curSize > mMuteListSize)
type = ADD;
else if(curSize < mMuteListSize)
type = REMOVE;
return type;
}
void LLBlockList::onChangeDetailed(const LLMute &mute)
{
mActionType = getCurrentMuteListActionType();
mCurItemId = mute.mID;
mCurItemName = mute.mName;
mCurItemType = mute.mType;
mCurItemFlags = mute.mFlags;
refresh();
}
BOOL LLBlockList::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask);
LLToggleableMenu* context_menu = mContextMenu.get();
if (context_menu && size())
{
context_menu->buildDrawLabels();
context_menu->updateParent(LLMenuGL::sMenuContainer);
LLMenuGL::showPopup(this, context_menu, x, y);
}
return handled;
}
void LLBlockList::removeListItem(const LLMute* mute)
{
removeItemByUUID(mute->mID);
}
void LLBlockList::hideListItem(LLBlockedListItem* item, bool show)
{
item->setVisible(show);
}
void LLBlockList::setNameFilter(const std::string& filter)
{
std::string filter_upper = filter;
LLStringUtil::toUpper(filter_upper);
if (mNameFilter != filter_upper)
{
mNameFilter = filter_upper;
setDirty();
}
}
void LLBlockList::sortByName()
{
setComparator(&NAME_COMPARATOR);
sort();
}
void LLBlockList::sortByType()
{
setComparator(&NAME_TYPE_COMPARATOR);
sort();
}
void LLBlockList::draw()
{
if (mDirty)
{
refresh();
}
LLFlatListView::draw();
}
void LLBlockList::addNewItem(const LLMute* mute)
{
LLBlockedListItem* item = new LLBlockedListItem(mute);
if (!mNameFilter.empty())
{
item->highlightName(mNameFilter);
}
addItem(item, item->getUUID(), ADD_BOTTOM);
}
void LLBlockList::refresh()
{
bool have_filter = !mNameFilter.empty();
// save selection to restore it after list rebuilt
LLUUID selected = getSelectedUUID(), next_selected;
if(mShouldAddAll) // creating list of blockers
{
clear();
createList();
mShouldAddAll = false;
}
else
{
// handle remove/add functionality
LLMute mute(mCurItemId, mCurItemName, mCurItemType, mCurItemFlags);
if(mActionType == ADD)
{
addNewItem(&mute);
}
else if(mActionType == REMOVE)
{
if(selected == mute.mID)
{
// we are going to remove currently selected item, so select next item and save the selection to restore it
if (!selectNextItemPair(false, true))
{
selectNextItemPair(true, true);
}
next_selected = getSelectedUUID();
}
removeListItem(&mute);
}
mActionType = NONE;
}
// handle filter functionality
if(have_filter || (!have_filter && !mPrevNameFilter.empty()))
{
// we should update visibility of our items if previous filter was not empty
std::vector < LLPanel* > allItems;
getItems(allItems);
std::vector < LLPanel* >::iterator it = allItems.begin();
for(; it != allItems.end() ; ++it)
{
LLBlockedListItem * curItem = dynamic_cast<LLBlockedListItem *> (*it);
if(curItem)
{
hideListItem(curItem, findInsensitive(curItem->getName(), mNameFilter));
}
}
}
mPrevNameFilter = mNameFilter;
if (getItemPair(selected))
{
// restore previously selected item
selectItemPair(getItemPair(selected), true);
}
else if (getItemPair(next_selected))
{
// previously selected item was removed, so select next item
selectItemPair(getItemPair(next_selected), true);
}
mMuteListSize = LLMuteList::getInstance()->getMutes().size();
// Sort the list.
sort();
setDirty(false);
}
bool LLBlockList::findInsensitive(std::string haystack, const std::string& needle_upper)
{
LLStringUtil::toUpper(haystack);
return haystack.find(needle_upper) != std::string::npos;
}
LLBlockedListItem* LLBlockList::getBlockedItem() const
{
LLPanel* panel = LLFlatListView::getSelectedItem();
LLBlockedListItem* item = dynamic_cast<LLBlockedListItem*>(panel);
return item;
}
bool LLBlockList::isActionEnabled(const LLSD& userdata)
{
bool action_enabled = true;
const std::string command_name = userdata.asString();
if ("profile_item" == command_name
|| "block_voice" == command_name
|| "block_text" == command_name
|| "block_particles" == command_name
|| "block_obj_sounds" == command_name)
{
// <FS:Ansariel> Blocklist multi selection
//LLBlockedListItem* item = getBlockedItem();
//action_enabled = item && (LLMute::AGENT == item->getType());
std::vector<LLPanel*> panels;
getSelectedItems(panels);
if (panels.size() == 1)
{
LLBlockedListItem* item = dynamic_cast<LLBlockedListItem*>(panels.front());
action_enabled = item && (LLMute::AGENT == item->getType());
}
else
{
action_enabled = false;
}
// </FS:Ansariel>
}
if ("unblock_item" == command_name)
{
action_enabled = getSelectedItem() != NULL;
}
return action_enabled;
}
void LLBlockList::onCustomAction(const LLSD& userdata)
{
if (!isActionEnabled(userdata))
{
return;
}
// <FS:Ansariel> Blocklist multi selection
//LLBlockedListItem* item = getBlockedItem();
const std::string command_name = userdata.asString();
if ("unblock_item" == command_name)
{
// <FS:Ansariel> Blocklist multi selection
//LLMute mute(item->getUUID(), item->getName());
//LLMuteList::getInstance()->remove(mute);
std::vector<LLPanel*> panels;
getSelectedItems(panels);
for (std::vector<LLPanel*>::iterator it = panels.begin(); it != panels.end(); ++it)
{
LLBlockedListItem* item = dynamic_cast<LLBlockedListItem*>(*it);
if (item)
{
LLMute mute(item->getUUID(), item->getName());
LLMuteList::getInstance()->remove(mute);
}
}
// </FS:Ansariel>
}
else if ("profile_item" == command_name)
{
// <FS:Ansariel> Blocklist multi selection
LLBlockedListItem* item = getBlockedItem();
switch(item->getType())
{
case LLMute::AGENT:
LLAvatarActions::showProfile(item->getUUID());
break;
default:
break;
}
}
else if ("block_voice" == command_name)
{
toggleMute(LLMute::flagVoiceChat);
}
else if ("block_text" == command_name)
{
toggleMute(LLMute::flagTextChat);
}
else if ("block_particles" == command_name)
{
toggleMute(LLMute::flagParticles);
}
else if ("block_obj_sounds" == command_name)
{
toggleMute(LLMute::flagObjectSounds);
}
}
bool LLBlockList::isMenuItemChecked(const LLSD& userdata)
{
LLBlockedListItem* item = getBlockedItem();
if (!item)
{
return false;
}
const std::string command_name = userdata.asString();
if ("block_voice" == command_name)
{
return LLMuteList::getInstance()->isMuted(item->getUUID(), LLMute::flagVoiceChat);
}
else if ("block_text" == command_name)
{
return LLMuteList::getInstance()->isMuted(item->getUUID(), LLMute::flagTextChat);
}
else if ("block_particles" == command_name)
{
return LLMuteList::getInstance()->isMuted(item->getUUID(), LLMute::flagParticles);
}
else if ("block_obj_sounds" == command_name)
{
return LLMuteList::getInstance()->isMuted(item->getUUID(), LLMute::flagObjectSounds);
}
return false;
}
bool LLBlockList::isMenuItemVisible(const LLSD& userdata)
{
LLBlockedListItem* item = getBlockedItem();
const std::string command_name = userdata.asString();
if ("block_voice" == command_name
|| "block_text" == command_name
|| "block_particles" == command_name
|| "block_obj_sounds" == command_name)
{
return item && (LLMute::AGENT == item->getType());
}
return false;
}
void LLBlockList::toggleMute(U32 flags)
{
LLBlockedListItem* item = getBlockedItem();
LLMute mute(item->getUUID(), item->getName(), item->getType());
if (!LLMuteList::getInstance()->isMuted(item->getUUID(), flags))
{
LLMuteList::getInstance()->add(mute, flags);
}
else
{
LLMuteList::getInstance()->remove(mute, flags);
}
}
bool LLBlockListItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const
{
const LLBlockedListItem* blocked_item1 = dynamic_cast<const LLBlockedListItem*>(item1);
const LLBlockedListItem* blocked_item2 = dynamic_cast<const LLBlockedListItem*>(item2);
if (!blocked_item1 || !blocked_item2)
{
LL_ERRS() << "blocked_item1 and blocked_item2 cannot be null" << LL_ENDL;
return true;
}
return doCompare(blocked_item1, blocked_item2);
}
bool LLBlockListNameComparator::doCompare(const LLBlockedListItem* blocked_item1, const LLBlockedListItem* blocked_item2) const
{
std::string name1 = blocked_item1->getName();
std::string name2 = blocked_item2->getName();
LLStringUtil::toUpper(name1);
LLStringUtil::toUpper(name2);
return name1 < name2;
}
bool LLBlockListNameTypeComparator::doCompare(const LLBlockedListItem* blocked_item1, const LLBlockedListItem* blocked_item2) const
{
LLMute::EType type1 = blocked_item1->getType();
LLMute::EType type2 = blocked_item2->getType();
// if mute type is LLMute::BY_NAME or LLMute::OBJECT it means that this mute is an object
bool both_mutes_are_objects = (LLMute::OBJECT == type1 || LLMute::BY_NAME == type1) && (LLMute::OBJECT == type2 || LLMute::BY_NAME == type2);
// mute types may be different, but since both LLMute::BY_NAME and LLMute::OBJECT types represent objects
// it's needed to perform additional checking of both_mutes_are_objects variable
if (type1 != type2 && !both_mutes_are_objects)
{
// objects in block list go first, so return true if mute type is not an avatar
return LLMute::AGENT != type1;
}
return NAME_COMPARATOR.compare(blocked_item1, blocked_item2);
}