Initial drop of new Contact Sets UI, fixes FIRE-10402, FIRE-11346 (and FIRE-5390 if using the new UI)

TODO: signal refresh to avatar list when an avatar is added from right click menu, confirm removal of avatar from set, possible other bugs, possible removal or lggcontactsetsfloater
Cinders 2013-11-19 17:01:37 -07:00
parent 96f8affcb1
commit fdcd99ae34
27 changed files with 1158 additions and 18 deletions

View File

@ -133,7 +133,9 @@ set(viewer_SOURCE_FILES
fscontactsfloater.cpp
fsdata.cpp
fsexportperms.cpp
fsfloateraddtocontactset.cpp
fsfloaterblocklist.cpp
fsfloatercontactsetconfiguration.cpp
fsfloaterexport.cpp
fsfloatergroup.cpp
fsfloatergrouptitles.cpp
@ -162,6 +164,7 @@ set(viewer_SOURCE_FILES
fsnearbychathub.cpp
fsnearbychatvoicemonitor.cpp
fspanelclassified.cpp
fspanelcontactsets.cpp
fspanelimcontrolpanel.cpp
fspanelprefs.cpp
fspanelprofile.cpp
@ -828,7 +831,9 @@ set(viewer_HEADER_FILES
fscontactsfloater.h
fsdata.h
fsexportperms.h
fsfloateraddtocontactset.h
fsfloaterblocklist.h
fsfloatercontactsetconfiguration.h
fsfloaterexport.h
fsfloatergroup.h
fsfloatergrouptitles.h
@ -857,6 +862,7 @@ set(viewer_HEADER_FILES
fsnearbychatcontrol.h
fsnearbychathub.h
fsnearbychatvoicemonitor.h
fspanelcontactsets.h
fspanelclassified.h
fspanelimcontrolpanel.h
fspanelprefs.h

View File

@ -443,6 +443,11 @@ std::string FSFloaterContacts::getActiveTabName() const
return mTabContainer->getCurrentPanel()->getName();
}
LLPanel* FSFloaterContacts::getPanelByName(const std::string& panel_name)
{
return mTabContainer->getPanelByName(panel_name);
}
LLUUID FSFloaterContacts::getCurrentItemID() const
{
std::string cur_tab = getActiveTabName();

View File

@ -62,6 +62,7 @@ public:
static FSFloaterContacts* findInstance();
void openTab(const std::string& name);
LLPanel* getPanelByName(const std::string& panel_name);
void sortFriendList();

View File

@ -0,0 +1,93 @@
/*
* @file fsfloateraddtocontactset.cpp
* @brief Add an avatar to a contact set
*
* (C) 2013 Cinder Roxley @ Second Life <cinder.roxley@phoenixviewer.com>
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "llviewerprecompiledheaders.h"
#include "fsfloateraddtocontactset.h"
#include "llnotificationsutil.h"
#include "llslurl.h"
#include <boost/foreach.hpp>
FSFloaterAddToContactSet::FSFloaterAddToContactSet(const LLSD& target)
: LLFloater(target)
, mContactSetsCombo(NULL)
{
mAgentID = target.asUUID();
}
BOOL FSFloaterAddToContactSet::postBuild()
{
childSetTextArg("textfield", "[NAME]", LLSLURL("agent", mAgentID, "inspect").getSLURLString());
mContactSetsCombo = getChild<LLComboBox>("contact_sets");
populateContactSets();
childSetAction("add_btn", boost::bind(&FSFloaterAddToContactSet::onClickAdd, this));
childSetAction("cancel_btn", boost::bind(&FSFloaterAddToContactSet::onClickCancel, this));
return TRUE;
}
void FSFloaterAddToContactSet::onClickAdd()
{
const std::string set = mContactSetsCombo->getSimple();
if (LGGContactSets::getInstance()->isNonFriend(mAgentID))
LGGContactSets::getInstance()->addNonFriendToList(mAgentID);
LGGContactSets::getInstance()->addFriendToGroup(mAgentID, set);
LLSD args;
args["NAME"] = LLSLURL("agent", mAgentID, "inspect").getSLURLString();
args["SET"] = set;
LLNotificationsUtil::add("AddToContactSetSuccess", args);
closeFloater();
}
void FSFloaterAddToContactSet::onClickCancel()
{
closeFloater();
}
void FSFloaterAddToContactSet::populateContactSets()
{
if (!mContactSetsCombo) return;
mContactSetsCombo->clear();
std::vector<std::string> contact_sets = LGGContactSets::getInstance()->getAllGroups();
if (contact_sets.empty())
{
mContactSetsCombo->add(getString("no_sets"), LLSD(NULL));
getChild<LLButton>("add_btn")->setEnabled(FALSE);
}
else
{
BOOST_FOREACH(const std::string& set_name, contact_sets)
{
mContactSetsCombo->add(set_name);
}
}
}

View File

@ -0,0 +1,55 @@
/*
* @file fsfloateraddtocontactset.h
* @brief Add an avatar to a contact set
*
* (C) 2013 Cinder Roxley @ Second Life <cinder.roxley@phoenixviewer.com>
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef FS_FLOATERADDTOCONTACTSET_H
#define FS_FLOATERADDTOCONTACTSET_H
#include "llfloater.h"
#include "llcombobox.h"
#include "lggcontactsets.h"
class FSFloaterAddToContactSet : public LLFloater
{
public:
FSFloaterAddToContactSet(const LLSD& target);
BOOL postBuild();
private:
~FSFloaterAddToContactSet(){};
void onClickAdd();
void onClickCancel();
void populateContactSets();
LLUUID mAgentID;
LLComboBox* mContactSetsCombo;
};
#endif // FS_FLOATERADDTOCONTACTSET_H

View File

@ -0,0 +1,86 @@
/*
* @file fsfloatercontactsetconfiguration.cpp
* @brief Contact set configuration floater
*
* (C) 2013 Cinder Roxley @ Second Life <cinder.roxley@phoenixviewer.com>
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "llviewerprecompiledheaders.h"
#include "fsfloatercontactsetconfiguration.h"
#include "lggcontactsets.h"
FSFloaterContactSetConfiguration::FSFloaterContactSetConfiguration(const LLSD& target_set)
: LLFloater(target_set)
{
mContactSet = target_set.asString();
}
BOOL FSFloaterContactSetConfiguration::postBuild()
{
LLStringUtil::format_map_t map;
map["NAME"] = mContactSet;
setTitle(getString("title", map));
mSetSwatch = getChild<LLColorSwatchCtrl>("set_swatch");
if (mSetSwatch)
{
mSetSwatch->setCommitCallback(boost::bind(&FSFloaterContactSetConfiguration::onCommitSetColor, this));
}
mGlobalSwatch = getChild<LLColorSwatchCtrl>("global_swatch");
if (mGlobalSwatch)
{
mGlobalSwatch->setCommitCallback(boost::bind(&FSFloaterContactSetConfiguration::onCommitDefaultColor, this));
}
mNotificationCheckBox = getChild<LLCheckBoxCtrl>("show_set_notifications");
if (mNotificationCheckBox)
{
mNotificationCheckBox->setCommitCallback(boost::bind(&FSFloaterContactSetConfiguration::onCommitSetNotifications, this));
}
return TRUE;
}
void FSFloaterContactSetConfiguration::onOpen(const LLSD& target_set)
{
mSetSwatch->set(LGGContactSets::getInstance()->getGroupColor(mContactSet), TRUE);
mGlobalSwatch->set(LGGContactSets::getInstance()->getDefaultColor(), TRUE);
mNotificationCheckBox->set(LGGContactSets::getInstance()->getNotifyForGroup(mContactSet));
}
void FSFloaterContactSetConfiguration::onCommitSetColor()
{
LGGContactSets::getInstance()->setGroupColor(mContactSet, mSetSwatch->get());
}
void FSFloaterContactSetConfiguration::onCommitSetNotifications()
{
LGGContactSets::getInstance()->setNotifyForGroup(mContactSet, mNotificationCheckBox->getValue().asBoolean());
}
void FSFloaterContactSetConfiguration::onCommitDefaultColor()
{
LGGContactSets::getInstance()->setDefaultColor(mGlobalSwatch->get());
}

View File

@ -0,0 +1,58 @@
/*
* @file fsfloatercontactsetconfiguration.h
* @brief Contact set configuration floater definitions
*
* (C) 2013 Cinder Roxley @ Second Life <cinder.roxley@phoenixviewer.com>
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef FS_FLOATERCONTACTSETCONFIGURATION_H
#define FS_FLOATERCONTACTSETCONFIGURATION_H
#include "llfloater.h"
#include "llcheckboxctrl.h"
#include "llcolorswatch.h"
class FSFloaterContactSetConfiguration : public LLFloater
{
public:
FSFloaterContactSetConfiguration(const LLSD& target_set);
BOOL postBuild();
void onOpen(const LLSD& target_set);
private:
~FSFloaterContactSetConfiguration(){};
void onCommitSetColor();
void onCommitSetNotifications();
void onCommitDefaultColor();
// Wish there was something better to use for this...
std::string mContactSet;
LLCheckBoxCtrl* mNotificationCheckBox;
LLColorSwatchCtrl* mSetSwatch;
LLColorSwatchCtrl* mGlobalSwatch;
};
#endif //FS_FLOATERCONTACTSETCONFIGURATION_H

View File

@ -0,0 +1,288 @@
/*
* @file fspanelcontactsets.cpp
* @brief Contact sets UI
*
* (C) 2013 Cinder Roxley @ Second Life <cinder.roxley@phoenixviewer.com>
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "llviewerprecompiledheaders.h"
#include "llnotificationsutil.h"
#include "fspanelcontactsets.h"
#include "fscontactsfloater.h"
#include "lggcontactsets.h"
#include "llavataractions.h"
#include "llcallingcard.h"
#include "llfloateravatarpicker.h"
#include "llfloaterreg.h"
#include "llslurl.h"
#include "lltrans.h"
#include <boost/foreach.hpp>
static LLRegisterPanelClassWrapper<FSPanelContactSets> t_panel_contact_sets("contact_sets_panel");
FSPanelContactSets::FSPanelContactSets() : LLPanel()
, mContactSetCombo(NULL)
, mAvatarList(NULL)
, mAvatarSelections(NULL)
{
}
BOOL FSPanelContactSets::postBuild()
{
childSetAction("add_set_btn", boost::bind(&FSPanelContactSets::onClickAddSet, this));
childSetAction("remove_set_btn", boost::bind(&FSPanelContactSets::onClickRemoveSet, this));
childSetAction("config_btn", boost::bind(&FSPanelContactSets::onClickConfigureSet, this));
childSetAction("add_btn", boost::bind(&FSPanelContactSets::onClickAddAvatar, this));
childSetAction("remove_btn", boost::bind(&FSPanelContactSets::onClickRemoveAvatar, this));
childSetAction("profile_btn", boost::bind(&FSPanelContactSets::onClickOpenProfile, this));
childSetAction("start_im_btn", boost::bind(&FSPanelContactSets::onClickStartIM, this));
childSetAction("offer_teleport_btn", boost::bind(&FSPanelContactSets::onClickOfferTeleport, this));
mContactSetCombo = getChild<LLComboBox>("combo_sets");
if (mContactSetCombo)
{
mContactSetCombo->setCommitCallback(boost::bind(&FSPanelContactSets::onSelectContactSet, this));
refreshContactSets();
}
mAvatarList = getChild<LLAvatarList>("contact_list");
if (mAvatarList)
{
mAvatarList->setCommitCallback(boost::bind(&FSPanelContactSets::onSelectAvatar, this));
mAvatarList->setNoItemsCommentText(getString("empty_list"));
generateAvatarList(mContactSetCombo->getSimple());
}
return TRUE;
}
void FSPanelContactSets::onSelectAvatar()
{
mAvatarSelections.clear();
mAvatarList->getSelectedUUIDs(mAvatarSelections);
resetControls();
}
void FSPanelContactSets::generateAvatarList(const std::string& contact_set)
{
if (!mAvatarList) return;
uuid_vec_t& avatars = mAvatarList->getIDs();
avatars.clear();
if (contact_set == getString("no_sets"))
{
}
//else if (contact_set == "Friends")
//{
// LLAvatarTracker::buddy_map_t buddies;
// LLAvatarTracker::instance().copyBuddyList(buddies);
// LLAvatarTracker::buddy_map_t::const_iterator buddy = buddies.begin();
// for (; buddy != buddies.end(); ++buddy)
// {
// avatars.push_back(buddy->first);
// }
//}
else
{
LGGContactSets::ContactSetGroup* group = LGGContactSets::getInstance()->getGroup(contact_set); // UGLY!
BOOST_FOREACH(const LLUUID id, group->mFriends)
{
avatars.push_back(id);
}
}
mAvatarList->setDirty();
resetControls();
}
void FSPanelContactSets::resetControls()
{
bool has_sets = (!LGGContactSets::getInstance()->getAllGroups().empty());
bool has_selection = mAvatarSelections.size();
childSetEnabled("remove_set_btn", has_sets);
childSetEnabled("config_btn", has_sets);
childSetEnabled("add_btn", has_sets);
childSetEnabled("remove_btn", (has_sets && has_selection));
childSetEnabled("profile_btn", has_selection);
childSetEnabled("start_im_btn", has_selection);
childSetEnabled("offer_teleport_btn", has_selection); // Should probably check if they're online...
}
void FSPanelContactSets::refreshContactSets()
{
if (!mContactSetCombo) return;
mContactSetCombo->clearRows();
std::vector<std::string> contact_sets = LGGContactSets::getInstance()->getAllGroups();
if (!contact_sets.empty())
{
BOOST_FOREACH(const std::string& set_name, contact_sets)
{
mContactSetCombo->add(set_name);
}
}
else
{
mContactSetCombo->add(getString("no_sets"), LLSD("No Set"));
}
// This only gets enabled for testing.
//mContactSetCombo->add(LLTrans::getString("InvFolder Friends"), LLSD("Friends"), ADD_TOP);
resetControls();
}
void FSPanelContactSets::onSelectContactSet()
{
generateAvatarList(mContactSetCombo->getSimple());
resetControls();
}
void FSPanelContactSets::onClickAddAvatar()
{
LLFloater* root_floater = gFloaterView->getParentFloater(this);
LLFloater* avatar_picker = LLFloaterAvatarPicker::show(boost::bind(&FSPanelContactSets::handlePickerCallback, this, _1, mContactSetCombo->getSimple()),
TRUE, TRUE, TRUE, root_floater->getName());
if (root_floater && avatar_picker)
root_floater->addDependentFloater(avatar_picker);
}
void FSPanelContactSets::handlePickerCallback(const uuid_vec_t& ids, const std::string& set)
{
if (ids.empty() || !mContactSetCombo) return;
BOOST_FOREACH(const LLUUID& id, ids)
{
if (LGGContactSets::getInstance()->isNonFriend(id))
LGGContactSets::getInstance()->addNonFriendToList(id);
LGGContactSets::getInstance()->addFriendToGroup(id, set);
}
// Only refresh the list if it's currently open.
if (set == mContactSetCombo->getSimple())
generateAvatarList(set);
}
void FSPanelContactSets::onClickRemoveAvatar()
{
if (!(mAvatarList && mContactSetCombo)) return;
std::string set = mContactSetCombo->getSimple();
BOOST_FOREACH(const LLUUID& id, mAvatarSelections)
{
LGGContactSets::getInstance()->removeFriendFromGroup(id, set);
if (LGGContactSets::getInstance()->isNonFriend(id))
LGGContactSets::getInstance()->removeNonFriendFromList(id);
}
if (set == mContactSetCombo->getSimple())
generateAvatarList(set);
}
void FSPanelContactSets::onClickAddSet()
{
LLNotificationsUtil::add("AddNewContactSet", LLSD(), LLSD(), &handleAddContactSetCallback);
}
void FSPanelContactSets::onClickRemoveSet()
{
LLSD payload, args;
std::string set = mContactSetCombo->getSimple();
args["SET_NAME"] = set;
payload["contact_set"] = set;
LLNotificationsUtil::add("RemoveContactSet", args, payload, &handleRemoveContactSetCallback);
}
void FSPanelContactSets::onClickConfigureSet()
{
LLFloater* root_floater = gFloaterView->getParentFloater(this);
LLFloater* config_floater = LLFloaterReg::showInstance("fs_contact_set_config", LLSD(mContactSetCombo->getSimple()));
if (root_floater && config_floater)
root_floater->addDependentFloater(config_floater);
}
void FSPanelContactSets::onClickOpenProfile()
{
BOOST_FOREACH(const LLUUID& id, mAvatarSelections)
{
LLAvatarActions::showProfile(id);
}
}
void FSPanelContactSets::onClickStartIM()
{
if ( mAvatarSelections.size() == 1 )
{
LLAvatarActions::startIM(mAvatarSelections[0]);
}
else if ( mAvatarSelections.size() > 1 )
{
LLAvatarActions::startConference(mAvatarSelections);
}
}
void FSPanelContactSets::onClickOfferTeleport()
{
LLAvatarActions::offerTeleport(mAvatarSelections);
}
////////////////////
// Static methods //
////////////////////
// static
bool FSPanelContactSets::handleAddContactSetCallback(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
{
std::string set_name = response["message"].asString();
LGGContactSets::getInstance()->addGroup(set_name);
FSPanelContactSets* panel = dynamic_cast<FSPanelContactSets*>(FSFloaterContacts::findInstance()->getPanelByName("contact_sets_panel"));
if (panel)
{
panel->refreshContactSets();
panel->mContactSetCombo->setSimple(set_name);
panel->generateAvatarList(set_name);
}
}
return false;
}
// static
bool FSPanelContactSets::handleRemoveContactSetCallback(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
{
LGGContactSets::getInstance()->deleteGroup(notification["payload"]["contact_set"].asString());
FSPanelContactSets* panel = dynamic_cast<FSPanelContactSets*>(FSFloaterContacts::findInstance()->getPanelByName("contact_sets_panel"));
if (panel)
{
panel->refreshContactSets();
panel->generateAvatarList(panel->mContactSetCombo->getSimple());
}
}
return false;
}

View File

@ -0,0 +1,74 @@
/*
* @file fspanelcontactsets.h
* @brief Contact sets UI defintions
*
* (C) 2013 Cinder Roxley @ Second Life <cinder.roxley@phoenixviewer.com>
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef FS_PANELCONTACTSETS_H
#define FS_PANELCONTACTSETS_H
#include "llavatarlist.h"
#include "llcombobox.h"
#include "llpanel.h"
#include <boost/signals2.hpp>
class FSPanelContactSets : public LLPanel
{
public:
FSPanelContactSets();
BOOL postBuild();
private:
~FSPanelContactSets(){};
void onSelectAvatar();
void generateAvatarList(const std::string& contact_set);
void onClickAddAvatar();
void handlePickerCallback(const uuid_vec_t& ids, const std::string& set);
void onClickRemoveAvatar();
void onClickOpenProfile();
void onClickStartIM();
void onClickOfferTeleport();
void onSelectContactSet();
void onClickAddSet();
void onClickRemoveSet();
void onClickConfigureSet();
void refreshContactSets();
void removeAvatarFromSet();
void resetControls();
static bool handleAddContactSetCallback(const LLSD& notification, const LLSD& response);
static bool handleRemoveContactSetCallback(const LLSD& notification, const LLSD& response);
static bool handleRemoveAvatarFromSetCallback(const LLSD& notification, const LLSD& response);
uuid_vec_t mAvatarSelections;
LLComboBox* mContactSetCombo;
LLAvatarList* mAvatarList;
};
#endif // FS_PANELCONTACTSETS_H

View File

@ -694,6 +694,7 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()
registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::share, mUUIDs.front()));
registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, mUUIDs.front()));
registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startCall, mUUIDs.front()));
registrar.add("Avatar.AddToContactSet", boost::bind(&LLAvatarActions::addToContactSet, mUUIDs.front()));
registrar.add("ParticipantList.ModerateVoice", boost::bind(&LLParticipantList::LLParticipantListMenu::moderateVoice, this, _2));

View File

@ -82,6 +82,7 @@ LLContextMenu* FSRadarMenu::createMenu()
registrar.add("Avatar.EstateBan", boost::bind(&LLAvatarActions::estateBan, id));
registrar.add("Avatar.Derender", boost::bind(&LLAvatarActions::derender, id, false));
registrar.add("Avatar.DerenderPermanent", boost::bind(&LLAvatarActions::derender, id, true));
registrar.add("Avatar.AddToContactSet", boost::bind(&LLAvatarActions::addToContactSet, id));
registrar.add("Nearby.People.TeleportToAvatar", boost::bind(&FSRadarMenu::teleportToAvatar, this));
registrar.add("Nearby.People.TrackAvatar", boost::bind(&FSRadarMenu::onTrackAvatarMenuItemClick, this));

View File

@ -94,10 +94,8 @@ public:
bool isInternalGroupName(const std::string& groupName);
bool hasGroups() { return !mGroups.empty(); }
private:
typedef boost::unordered_set<LLUUID, FSUUIDHash> uuid_set_t;
typedef boost::unordered_map<LLUUID, std::string, FSUUIDHash> uuid_map_t;
class ContactSetGroup
{
@ -112,7 +110,10 @@ private:
bool mNotify;
LLColor4 mColor;
};
ContactSetGroup* getGroup(const std::string& groupName);
private:
typedef boost::unordered_map<LLUUID, std::string, FSUUIDHash> uuid_map_t;
LGGContactSets();
~LGGContactSets();
@ -136,8 +137,6 @@ private:
typedef std::map<std::string, ContactSetGroup*> group_map_t;
group_map_t mGroups;
ContactSetGroup* getGroup(const std::string& groupName);
void importFromLLSD(const LLSD& data);
LLSD exportToLLSD();
void saveToDisk();

View File

@ -1234,6 +1234,14 @@ void LLAvatarActions::viewChatHistoryExternally(const LLUUID& id)
}
// </FS:CR>
// [FS:CR] Add to contact set
//static
void LLAvatarActions::addToContactSet(const LLUUID& agent_id)
{
LLFloaterReg::showInstance("fs_add_contact", agent_id, TRUE);
}
// [/FS:CR] Add to contact set
//== private methods ========================================================================================
// static

View File

@ -197,6 +197,11 @@ public:
* Open csr page for avatar
*/
static void csr(const LLUUID& id, std::string name);
/**
* [FS:CR] Add avatar to contact set
*/
static void addToContactSet(const LLUUID& agent_id);
/**
* Checks whether we can offer a teleport to the avatar, only offline friends

View File

@ -85,6 +85,7 @@ LLContextMenu* PeopleContextMenu::createMenu()
registrar.add("Avatar.Calllog", boost::bind(&LLAvatarActions::viewChatHistory, id));
// <FS:Ansariel> Firestorm additions
registrar.add("Avatar.GroupInvite", boost::bind(&LLAvatarActions::inviteToGroup, id));
registrar.add("Avatar.AddToContactSet", boost::bind(&LLAvatarActions::addToContactSet, id)); // [FS:CR]
enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2));
enable_registrar.add("Avatar.CheckItem", boost::bind(&PeopleContextMenu::checkContextMenuItem, this, _2));

View File

@ -153,6 +153,8 @@
#include "floatermedialists.h"
#include "fsareasearch.h"
#include "fscontactsfloater.h"
#include "fsfloateraddtocontactset.h"
#include "fsfloatercontactsetconfiguration.h"
#include "fsfloaterexport.h"
#include "fsfloaterblocklist.h"
#include "fsfloatergroup.h"
@ -395,6 +397,8 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("delete_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDeleteQueue>);
LLFloaterReg::add("floater_profile", "floater_profile_view.xml",&LLFloaterReg::build<FSFloaterProfile>);
LLFloaterReg::add("fs_blocklist", "floater_fs_blocklist.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSFloaterBlocklist>);
LLFloaterReg::add("fs_add_contact", "floater_fs_contact_add.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSFloaterAddToContactSet>);
LLFloaterReg::add("fs_contact_set_config", "floater_fs_contact_set_configuration.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSFloaterContactSetConfiguration>);
LLFloaterReg::add("fs_group", "floater_fs_group.xml",&LLFloaterReg::build<FSFloaterGroup>);
LLFloaterReg::add("fs_group_titles", "floater_fs_group_titles.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSFloaterGroupTitles>);
LLFloaterReg::add("fs_export", "floater_fs_export.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSFloaterObjectExport>);

View File

@ -1344,7 +1344,7 @@ class LLAdvancedDumpScriptedCamera : public view_listener_t
{
handle_dump_followcam(NULL);
return true;
}
}
};
@ -1596,7 +1596,7 @@ class LLAdvancedLoadUIFromXML : public view_listener_t
{
handle_load_from_xml(NULL);
return true;
}
}
};
@ -1612,7 +1612,7 @@ class LLAdvancedSaveUIToXML : public view_listener_t
{
handle_save_to_xml(NULL);
return true;
}
}
};
@ -1622,7 +1622,7 @@ class LLAdvancedSendTestIms : public view_listener_t
{
LLIMModel::instance().testMessages();
return true;
}
}
};
@ -1767,7 +1767,7 @@ class LLAdvancedToggleCharacterGeometry : public view_listener_t
{
handle_god_request_avatar_geometry(NULL);
return true;
}
}
};
@ -9094,6 +9094,21 @@ class FSDumpSimulatorFeaturesToChat : public view_listener_t
};
// </FS:CR> Dump SimulatorFeatures to chat
// <FS:CR> Add to contact set
class FSAddToContactSet : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
LLVOAvatar* avatarp = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject());
if (avatarp)
{
LLFloaterReg::showInstance("fs_add_contact", LLSD(avatarp->getID()), TRUE);
}
return true;
}
};
// </FS:CR> Add to contact set
// <FS:CR> Opensim menu item visibility control
class LLGridCheck : public view_listener_t
{
@ -10909,6 +10924,8 @@ void initialize_menus()
view_listener_t::addMenu(new FSStreamListImportXML(), "Streamlist.xml_import");
// <FS:CR> Dump SimulatorFeatures to chat
view_listener_t::addMenu(new FSDumpSimulatorFeaturesToChat(), "Develop.DumpSimFeaturesToChat");
// <FS:CR> Add to contact set
view_listener_t::addMenu(new FSAddToContactSet(), "Avatar.AddToContactSet");
// <FS:Techwolf Lupindo> export
view_listener_t::addMenu(new FSObjectExport(), "Object.Export");

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
height="112"
width="280"
layout="topleft"
positioning="centered"
legacy_header_height="18"
can_resize="false"
name="floater_fs_add_contact"
title="Add to Contact Set...">
<floater.string
name="no_sets">
No contact sets available.
</floater.string>
<text
type="string"
follows="left|top"
height="35"
layout="topleft"
left="8"
name="textfield"
word_wrap="true"
top="20"
width="265">
Please select which contact set to add [NAME] to:
</text>
<combo_box
follows="left|top"
layout="topleft"
height="23"
allow_text_entry="false"
top_pad="4"
left="8"
name="contact_sets"
width="265"/>
<button
left="8"
top_pad="3"
follows="top|right"
layout="topleft"
height="22"
label="Add to set"
name="add_btn"
width="130" />
<button
left_pad="5"
top_delta="0"
follows="top|right"
layout="topleft"
height="22"
label="Cancel"
name="cancel_btn"
width="130" />
</floater>

View File

@ -0,0 +1,159 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
height="360"
width="380"
layout="topleft"
can_resize="false"
legacy_header_height="18"
name="floater_fs_contact_set_configure"
title="Contact set settings">
<floater.string
name="title">
[NAME] settings
</floater.string>
<panel
top="18"
left="0"
height="80"
width="380"
border_visible="true"
bevel_style="none">
<text
top="10"
follows="left|top"
layout="topleft"
left="10"
height="12"
name="set_label"
width="130">
Contact Set Settings:
</text>
<color_swatch
can_apply_immediately="true"
follows="left|top"
height="55"
label="Set Color"
top_pad="8"
left_delta="4"
name="set_swatch"
tool_tip="Click to open Color Picker"
width="65" />
<check_box
height="16"
label="Show notifications"
layout="topleft"
left_pad="4"
initial_value="false"
name="show_set_notifications"
top_delta="0"
width="400" />
</panel>
<panel
top_pad="0"
height="260"
width="380"
border_visible="true"
bevel_style="none">
<text
top="10"
follows="left|top"
layout="topleft"
left="10"
height="12"
name="global_label"
width="130">
Global Settings:
</text>
<color_swatch
can_apply_immediately="true"
follows="left|top"
height="55"
label="Default Set Color"
top_pad="8"
left_delta="4"
name="global_swatch"
tool_tip="Click to open Color Picker"
width="65" />
<text
top_pad="-2"
follows="left|top"
height="16"
left="15"
name="label_online"
width="200">
Online notifications:
</text>
<check_box
top_pad="4"
follows="left|top"
height="12"
label="Show Online Notices for ALL friends as toasts"
left_delta="5"
name="ChatOnlineNotification"
width="270"
control_name="ChatOnlineNotification"/>
<check_box
follows="left|top"
height="12"
label="Show Online Notices for ALL friends in nearby chat"
name="OnlineOfflinetoNearbyChat"
width="270"
control_name="OnlineOfflinetoNearbyChat"/>
<check_box
disabled_control="ChatOnlineNotification"
follows="left|top"
height="12"
label="Show Online Notices for certain Sets as toast"
name="FSContactSetsNotificationToast"
width="270"
control_name="FSContactSetsNotificationToast"/>
<check_box
disabled_control="OnlineOffLinetoNearbyChat"
follows="left|top"
height="12"
label="Show Online Notices for certain Sets in nearby chat"
name="FSContactSetsNotificationNearbyChat"
width="270"
control_name="FSContactSetsNotificationNearbyChat"/>
<text
top_pad="8"
follows="left|top"
height="16"
left="15"
name="label_colors"
width="200">
Custom Colors:
</text>
<check_box
top_pad="4"
follows="left|top"
height="12"
label="Color a friend's mini map icon based on their Contact Set"
left_delta="5"
name="FSContactSetsColorizeMiniMap"
width="270"
control_name="FSContactSetsColorizeMiniMap"/>
<check_box
follows="left|top"
height="12"
label="Color a friend's name tag based on their Contact Set"
name="FSContactSetsColorizeNameTag"
width="270"
control_name="FSContactSetsColorizeNameTag"/>
<check_box
follows="left|top"
height="12"
label="Color a friend's radar list entry based on their Contact Set"
name="FSContactSetsColorizeRadar"
width="270"
control_name="FSContactSetsColorizeRadar"/>
<check_box
follows="left|top"
height="12"
initial_value="false"
label="Color a friend's chat based on their Contact Set"
name="FSContactSetsColorizeChat"
width="270"
control_name="FSContactSetsColorizeChat"/>
</panel>
</floater>

View File

@ -65,15 +65,13 @@
right="-1"
name="groups_panel"/>
<!-- Ansariel: Commented out. XML file does not exist. What is it?
<panel
bottom="0"
filename="panel_fs_contacts_lists.xml"
label="Friends &amp; Contacts"
filename="panel_fs_contacts_sets.xml"
class="contact_sets_panel"
label="Contact Sets"
left="0"
right="-1"
name="contacts_lists_panel" />
-->
name="contact_sets_panel" />
</tab_container>
</floater>

View File

@ -22,6 +22,13 @@
<menu_item_call.on_enable
function="Avatar.EnableAddFriend" />
</menu_item_call>
<menu_item_call
label="Add to Set"
layout="topleft"
name="Add to Set">
<menu_item_call.on_click
function="Avatar.AddToContactSet" />
</menu_item_call>
<menu_item_call
label="IM"
name="Send IM...">

View File

@ -27,7 +27,14 @@
name="Add Calling Card">
<menu_item_call.on_click
function="Avatar.AddContact" />
</menu_item_call>
</menu_item_call>
<menu_item_call
label="Add to Set"
layout="topleft"
name="Add to Set">
<menu_item_call.on_click
function="Avatar.AddToContactSet" />
</menu_item_call>
<menu_item_call
label="IM"
name="Send IM...">

View File

@ -19,6 +19,13 @@
function="Avatar.EnableItem"
parameter="can_add" />
</menu_item_call>
<menu_item_call
label="Add to Set"
layout="topleft"
name="Add to Set">
<menu_item_call.on_click
function="Avatar.AddToContactSet" />
</menu_item_call>
<menu_item_call
label="Remove Friend"
layout="topleft"

View File

@ -22,6 +22,13 @@
function="ParticipantList.EnableItem"
parameter="can_add" />
</menu_item_call>
<menu_item_call
label="Add to Set"
layout="topleft"
name="Add to Set">
<menu_item_call.on_click
function="Avatar.AddToContactSet" />
</menu_item_call>
<menu_item_call
label="IM"
layout="topleft"

View File

@ -69,6 +69,13 @@
function="Avatar.EnableItem"
parameter="can_add" />
</menu_item_call>
<menu_item_call
label="Add to Set"
layout="topleft"
name="Add to Set">
<menu_item_call.on_click
function="Avatar.AddToContactSet" />
</menu_item_call>
<menu_item_call
label="Remove Friend"
layout="topleft"

View File

@ -11548,4 +11548,78 @@ The value you set for the number of concurrent requests to load mesh objects, [V
</form>
</notification>
<!-- <FS:Zi> Notification template for changed settings when selecting certain skins -->
<notification
icon="alertmodal.tga"
name="AddNewContactSet"
type="alertmodal">
<tag>contact set</tag>
Create new contact set with the name:
<tag>confirm</tag>
<form name="form">
<input name="message" type="text" default="true">
New Contact Set
</input>
<button
default="true"
index="0"
name="Create"
text="Create"/>
<button
index="1"
name="Cancel"
text="Cancel"/>
</form>
</notification>
<notification
icon="alertmodal.tga"
name="RemoveContactSet"
type="alertmodal">
Are you sure you want to remove [SET_NAME]? You won&apos;t be able to restore it.
<tag>contact set</tag>
<tag>confirm</tag>
<usetemplate
ignoretext="Confirm before removing a contact set"
name="okcancelignore"
notext="Cancel"
yestext="Ok"/>
</notification>
<notification
icon="alertmodal.tga"
name="RemoveContactFromSet"
type="alertmodal">
Are you sure you want to remove [NAME] from [SET_NAME]?
<tag>contact set</tag>
<tag>confirm</tag>
<usetemplate
ignoretext="Confirm before removing someone from a contact set"
name="okcancelignore"
notext="Cancel"
yestext="Ok"/>
</notification>
<notification
icon="alertmodal.tga"
name="RemoveContactsFromSet"
type="alertmodal">
Are you sure you want to remove [COUNT] avatars from [SET_NAME]?
<tag>contact set</tag>
<tag>confirm</tag>
<usetemplate
ignoretext="Confirm before removing multiple avatars from a contact set"
name="okcancelignore"
notext="Cancel"
yestext="Ok"/>
</notification>
<notification
icon="alertmodal.tga"
name="AddToContactSetSuccess"
type="notify">
<tag>Export</tag>
[NAME] was added to [SET].
</notification>
</notifications>

View File

@ -0,0 +1,118 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
height="300"
layout="topleft"
mouse_opaque="true"
name="contact_sets_panel"
width="355">
<panel.string
name="empty_list">
This contact set is empty.
</panel.string>
<panel.string
name="no_sets">
No contact sets available.
</panel.string>
<combo_box
follows="left|top|right"
layout="topleft"
height="18"
top="1"
left="4"
name="combo_sets"
width="204" />
<button
top_delta="0"
follows="top|right"
layout="topleft"
height="18"
image_overlay="Script_Config"
left_pad="1"
name="config_btn"
tool_tip="Configure selected contact set"
width="20" />
<button
top_delta="0"
follows="top|right"
layout="topleft"
height="18"
image_overlay="AddItem_Off"
left_pad="1"
name="add_set_btn"
tool_tip="Add a new contact set"
width="20" />
<button
top_delta="0"
follows="top|right"
layout="topleft"
height="18"
image_overlay="MinusItem_Off"
left_pad="1"
name="remove_set_btn"
tool_tip="Remove selected contact set"
width="20" />
<avatar_list
left="4"
right="-85"
top="20"
bottom="-3"
follows="all"
layout="topleft"
ignore_online_status="true"
show_profile_button="true"
show_speaking_indicator="false"
show_voice_volume="false"
show_permissions_granted="true"
show_icons="true"
allow_select="true"
multi_select="true"
keep_one_selected="false"
name="contact_list" />
<!-- Action buttons -->
<button
top="1"
follows="top|right"
layout="topleft"
height="22"
label="Add..."
left_delta="270"
name="add_btn"
tool_tip="Add an avatar to the current contact set"
width="80" />
<button
top_pad="3"
follows="top|right"
layout="topleft"
height="22"
label="Remove..."
name="remove_btn"
tool_tip="Remove this avatar from the current contact set"
width="80" />
<button
top_pad="3"
follows="top|right"
layout="topleft"
height="22"
label="Profile..."
name="profile_btn"
tool_tip="Open this avatar's profile"
width="80" />
<button
top_pad="3"
follows="top|right"
layout="topleft"
height="22"
label="IM..."
name="start_im_btn"
tool_tip="Begin an instant message conversation"
width="80" />
<button
top_pad="3"
follows="top|right"
layout="topleft"
height="22"
label="Teleport..."
name="offer_teleport_btn"
tool_tip="Offer a teleport to your current location"
width="80" />
</panel>