394 lines
9.9 KiB
C++
Executable File
394 lines
9.9 KiB
C++
Executable File
/**
|
|
* @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));
|
|
|
|
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)
|
|
{
|
|
// <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;
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|