Add support for pinning/unpinning groups in people panel and contacts floater
Signed-off-by: PanteraPolnocy <panterapolnocy@gmail.com>master
parent
a1ba797c46
commit
77023234d3
|
|
@ -114,6 +114,7 @@ set(viewer_SOURCE_FILES
|
|||
fsdroptarget.cpp
|
||||
fsexportperms.cpp
|
||||
fsfloateraddtocontactset.cpp
|
||||
fsfavoritegroups.cpp
|
||||
fsfloaterassetblacklist.cpp
|
||||
fsfloateravatarrendersettings.cpp
|
||||
fsfloaterblocklist.cpp
|
||||
|
|
@ -956,6 +957,7 @@ set(viewer_HEADER_FILES
|
|||
fsdroptarget.h
|
||||
fsexportperms.h
|
||||
fsfloateraddtocontactset.h
|
||||
fsfavoritegroups.h
|
||||
fsfloaterassetblacklist.h
|
||||
fsfloateravatarrendersettings.h
|
||||
fsfloaterblocklist.h
|
||||
|
|
|
|||
|
|
@ -1374,6 +1374,17 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSFavoriteGroups</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>List of favorite/pinned group UUIDs</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>LLSD</string>
|
||||
<key>Value</key>
|
||||
<array></array>
|
||||
</map>
|
||||
<key>FSMaxSharedMaturity</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,137 @@
|
|||
/**
|
||||
* @file fsfavoritegroups.cpp
|
||||
* @brief Favorite groups storage management
|
||||
*
|
||||
* $LicenseInfo:firstyear=2025&license=viewerlgpl$
|
||||
* Phoenix Firestorm Viewer Source Code
|
||||
* Copyright (C) 2025, The Phoenix Firestorm Project, 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
|
||||
*
|
||||
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
|
||||
* http://www.firestormviewer.org
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "fsfavoritegroups.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llviewercontrol.h"
|
||||
|
||||
FSFavoriteGroups::FSFavoriteGroups()
|
||||
{
|
||||
}
|
||||
|
||||
FSFavoriteGroups::~FSFavoriteGroups()
|
||||
{
|
||||
saveFavorites();
|
||||
}
|
||||
|
||||
bool FSFavoriteGroups::isFavorite(const LLUUID& group_id) const
|
||||
{
|
||||
return mFavoriteGroups.find(group_id) != mFavoriteGroups.end();
|
||||
}
|
||||
|
||||
void FSFavoriteGroups::addFavorite(const LLUUID& group_id)
|
||||
{
|
||||
if (group_id.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mFavoriteGroups.insert(group_id).second)
|
||||
{
|
||||
saveFavorites();
|
||||
mFavoritesChangedSignal();
|
||||
}
|
||||
}
|
||||
|
||||
void FSFavoriteGroups::removeFavorite(const LLUUID& group_id)
|
||||
{
|
||||
if (mFavoriteGroups.erase(group_id) > 0)
|
||||
{
|
||||
saveFavorites();
|
||||
mFavoritesChangedSignal();
|
||||
}
|
||||
}
|
||||
|
||||
void FSFavoriteGroups::toggleFavorite(const LLUUID& group_id)
|
||||
{
|
||||
if (isFavorite(group_id))
|
||||
{
|
||||
removeFavorite(group_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
addFavorite(group_id);
|
||||
}
|
||||
}
|
||||
|
||||
void FSFavoriteGroups::loadFavorites()
|
||||
{
|
||||
mFavoriteGroups.clear();
|
||||
|
||||
LLSD favorites = gSavedPerAccountSettings.getLLSD("FSFavoriteGroups");
|
||||
|
||||
if (favorites.isArray())
|
||||
{
|
||||
for (LLSD::array_const_iterator it = favorites.beginArray(); it != favorites.endArray(); ++it)
|
||||
{
|
||||
if (it->isUUID())
|
||||
{
|
||||
mFavoriteGroups.insert(it->asUUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LL_INFOS("FavoriteGroups") << "Loaded " << mFavoriteGroups.size() << " favorite groups from per-account settings" << LL_ENDL;
|
||||
}
|
||||
|
||||
void FSFavoriteGroups::saveFavorites()
|
||||
{
|
||||
|
||||
std::set<LLUUID> stale_groups;
|
||||
for (const auto& group_id : mFavoriteGroups)
|
||||
{
|
||||
if (!gAgent.isInGroup(group_id))
|
||||
{
|
||||
stale_groups.insert(group_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (!stale_groups.empty())
|
||||
{
|
||||
for (const auto& group_id : stale_groups)
|
||||
{
|
||||
mFavoriteGroups.erase(group_id);
|
||||
}
|
||||
LL_INFOS("FavoriteGroups") << "Removed " << stale_groups.size() << " stale group(s) from favorites (no longer a member)" << LL_ENDL;
|
||||
}
|
||||
|
||||
LLSD favorites_array = LLSD::emptyArray();
|
||||
|
||||
for (const auto& group_id : mFavoriteGroups)
|
||||
{
|
||||
favorites_array.append(group_id);
|
||||
}
|
||||
|
||||
gSavedPerAccountSettings.setLLSD("FSFavoriteGroups", favorites_array);
|
||||
|
||||
LL_DEBUGS("FavoriteGroups") << "Saved " << mFavoriteGroups.size() << " favorite groups to per-account settings" << LL_ENDL;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* @file fsfavoritegroups.h
|
||||
* @brief Favorite groups storage management
|
||||
*
|
||||
* $LicenseInfo:firstyear=2025&license=viewerlgpl$
|
||||
* Phoenix Firestorm Viewer Source Code
|
||||
* Copyright (C) 2025, The Phoenix Firestorm Project, 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
|
||||
*
|
||||
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
|
||||
* http://www.firestormviewer.org
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef FS_FAVORITEGROUPS_H
|
||||
#define FS_FAVORITEGROUPS_H
|
||||
|
||||
#include "llsingleton.h"
|
||||
#include "lluuid.h"
|
||||
#include <boost/signals2.hpp>
|
||||
#include <set>
|
||||
|
||||
class FSFavoriteGroups : public LLSingleton<FSFavoriteGroups>
|
||||
{
|
||||
LLSINGLETON(FSFavoriteGroups);
|
||||
~FSFavoriteGroups();
|
||||
|
||||
public:
|
||||
bool isFavorite(const LLUUID& group_id) const;
|
||||
void addFavorite(const LLUUID& group_id);
|
||||
void removeFavorite(const LLUUID& group_id);
|
||||
void toggleFavorite(const LLUUID& group_id);
|
||||
const std::set<LLUUID>& getFavorites() const { return mFavoriteGroups; }
|
||||
bool hasFavorites() const { return !mFavoriteGroups.empty(); }
|
||||
void loadFavorites();
|
||||
void saveFavorites();
|
||||
|
||||
typedef boost::signals2::signal<void()> favorites_changed_signal_t;
|
||||
boost::signals2::connection setFavoritesChangedCallback(const favorites_changed_signal_t::slot_type& cb)
|
||||
{
|
||||
return mFavoritesChangedSignal.connect(cb);
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<LLUUID> mFavoriteGroups;
|
||||
favorites_changed_signal_t mFavoritesChangedSignal;
|
||||
};
|
||||
|
||||
#endif // FS_FAVORITEGROUPS_H
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "fscommon.h"
|
||||
#include "fscontactsfriendsmenu.h"
|
||||
#include "fsfavoritegroups.h"
|
||||
#include "fsfloaterimcontainer.h"
|
||||
#include "fsscrolllistctrl.h"
|
||||
#include "llagent.h"
|
||||
|
|
@ -147,6 +148,7 @@ bool FSFloaterContacts::postBuild()
|
|||
mGroupsChatBtn = mGroupsTab->getChild<LLButton>("chat_btn");
|
||||
mGroupsInfoBtn = mGroupsTab->getChild<LLButton>("info_btn");
|
||||
mGroupsActivateBtn = mGroupsTab->getChild<LLButton>("activate_btn");
|
||||
mGroupsFavoriteBtn = mGroupsTab->getChild<LLButton>("favorite_btn");
|
||||
mGroupsLeaveBtn = mGroupsTab->getChild<LLButton>("leave_btn");
|
||||
mGroupsCreateBtn = mGroupsTab->getChild<LLButton>("create_btn");
|
||||
mGroupsSearchBtn = mGroupsTab->getChild<LLButton>("search_btn");
|
||||
|
|
@ -156,6 +158,7 @@ bool FSFloaterContacts::postBuild()
|
|||
mGroupsChatBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupChatButtonClicked, this));
|
||||
mGroupsInfoBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupInfoButtonClicked, this));
|
||||
mGroupsActivateBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupActivateButtonClicked, this));
|
||||
mGroupsFavoriteBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupFavoriteButtonClicked, this));
|
||||
mGroupsLeaveBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupLeaveButtonClicked, this));
|
||||
mGroupsCreateBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupCreateButtonClicked, this));
|
||||
mGroupsSearchBtn->setCommitCallback(boost::bind(&FSFloaterContacts::onGroupSearchButtonClicked, this));
|
||||
|
|
@ -247,6 +250,12 @@ void FSFloaterContacts::updateGroupButtons()
|
|||
mGroupsLeaveBtn->setEnabled(isGroup);
|
||||
mGroupsCreateBtn->setEnabled((!gMaxAgentGroups) || (gAgent.mGroups.size() < gMaxAgentGroups));
|
||||
mGroupsInviteBtn->setEnabled(isGroup && gAgent.hasPowerInGroup(groupId, GP_MEMBER_INVITE));
|
||||
mGroupsFavoriteBtn->setEnabled(isGroup);
|
||||
if (isGroup)
|
||||
{
|
||||
bool is_favorite = FSFavoriteGroups::getInstance()->isFavorite(groupId);
|
||||
mGroupsFavoriteBtn->setLabel(is_favorite ? getString("unfavorite_label") : getString("favorite_label"));
|
||||
}
|
||||
}
|
||||
|
||||
void FSFloaterContacts::onOpen(const LLSD& key)
|
||||
|
|
@ -432,6 +441,15 @@ void FSFloaterContacts::onGroupActivateButtonClicked()
|
|||
LLGroupActions::activate(mGroupList->getSelectedUUID());
|
||||
}
|
||||
|
||||
void FSFloaterContacts::onGroupFavoriteButtonClicked()
|
||||
{
|
||||
if (LLUUID group_id = getCurrentItemID(); group_id.notNull())
|
||||
{
|
||||
FSFavoriteGroups::getInstance()->toggleFavorite(group_id);
|
||||
updateGroupButtons();
|
||||
}
|
||||
}
|
||||
|
||||
void FSFloaterContacts::onGroupLeaveButtonClicked()
|
||||
{
|
||||
if (LLUUID group_id = getCurrentItemID(); group_id.notNull())
|
||||
|
|
|
|||
|
|
@ -141,6 +141,7 @@ private:
|
|||
void onGroupChatButtonClicked();
|
||||
void onGroupInfoButtonClicked();
|
||||
void onGroupActivateButtonClicked();
|
||||
void onGroupFavoriteButtonClicked();
|
||||
void onGroupLeaveButtonClicked();
|
||||
void onGroupCreateButtonClicked();
|
||||
void onGroupSearchButtonClicked();
|
||||
|
|
@ -167,6 +168,7 @@ private:
|
|||
LLButton* mGroupsChatBtn{ nullptr };
|
||||
LLButton* mGroupsInfoBtn{ nullptr };
|
||||
LLButton* mGroupsActivateBtn{ nullptr };
|
||||
LLButton* mGroupsFavoriteBtn{ nullptr };
|
||||
LLButton* mGroupsLeaveBtn{ nullptr };
|
||||
LLButton* mGroupsCreateBtn{ nullptr };
|
||||
LLButton* mGroupsSearchBtn{ nullptr };
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
// [RLVa:KB] - Checked: RLVa-2.0.3
|
||||
#include "rlvactions.h"
|
||||
// [/RLVa:KB]
|
||||
#include "fsfavoritegroups.h" // <FS:PP> Group favorites / pinning
|
||||
#include "llslurl.h"
|
||||
#include "llurlaction.h"
|
||||
|
||||
|
|
@ -59,8 +60,37 @@ public:
|
|||
/** Returns true if item1 < item2, false otherwise */
|
||||
/*virtual*/ bool compare(const LLPanel* item1, const LLPanel* item2) const
|
||||
{
|
||||
std::string name1 = static_cast<const LLGroupListItem*>(item1)->getGroupName();
|
||||
std::string name2 = static_cast<const LLGroupListItem*>(item2)->getGroupName();
|
||||
// <FS:PP> Group favorites / pinning
|
||||
// std::string name1 = static_cast<const LLGroupListItem*>(item1)->getGroupName();
|
||||
// std::string name2 = static_cast<const LLGroupListItem*>(item2)->getGroupName();
|
||||
|
||||
const LLGroupListItem* group_item1 = dynamic_cast<const LLGroupListItem*>(item1);
|
||||
const LLGroupListItem* group_item2 = dynamic_cast<const LLGroupListItem*>(item2);
|
||||
|
||||
if (!group_item1 || !group_item2)
|
||||
{
|
||||
if (!group_item1 && group_item2)
|
||||
{
|
||||
return group_item2->isFavorite() ? false : true;
|
||||
}
|
||||
if (group_item1 && !group_item2)
|
||||
{
|
||||
return group_item1->isFavorite() ? true : false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool fav1 = group_item1->isFavorite();
|
||||
bool fav2 = group_item2->isFavorite();
|
||||
|
||||
if (fav1 != fav2)
|
||||
{
|
||||
return fav1 > fav2;
|
||||
}
|
||||
|
||||
std::string name1 = group_item1->getGroupName();
|
||||
std::string name2 = group_item2->getGroupName();
|
||||
// </FS:PP>
|
||||
|
||||
LLStringUtil::toUpper(name1);
|
||||
LLStringUtil::toUpper(name2);
|
||||
|
|
@ -76,11 +106,22 @@ public:
|
|||
|
||||
/*virtual*/ bool compare(const LLPanel* item1, const LLPanel* item2) const
|
||||
{
|
||||
const LLGroupListItem* group_item1 = static_cast<const LLGroupListItem*>(item1);
|
||||
// <FS:PP> Group favorites / pinning
|
||||
const LLGroupListItem* group_item1 = dynamic_cast<const LLGroupListItem*>(item1);
|
||||
const LLGroupListItem* group_item2 = dynamic_cast<const LLGroupListItem*>(item2);
|
||||
if (!group_item1 || !group_item2)
|
||||
{
|
||||
// Sorting doesn't matter, as we hit a separator that shouldn't be visible in this view
|
||||
return false;
|
||||
}
|
||||
|
||||
// const LLGroupListItem* group_item1 = static_cast<const LLGroupListItem*>(item1);
|
||||
// </FS:PP>
|
||||
|
||||
std::string name1 = group_item1->getGroupName();
|
||||
bool item1_shared = gAgent.isInGroup(group_item1->getGroupID(), true);
|
||||
|
||||
const LLGroupListItem* group_item2 = static_cast<const LLGroupListItem*>(item2);
|
||||
// const LLGroupListItem* group_item2 = static_cast<const LLGroupListItem*>(item2); - <FS:PP> Group favorites / pinning
|
||||
std::string name2 = group_item2->getGroupName();
|
||||
bool item2_shared = gAgent.isInGroup(group_item2->getGroupID(), true);
|
||||
|
||||
|
|
@ -134,6 +175,12 @@ LLGroupList::~LLGroupList()
|
|||
{
|
||||
if (mForAgent) gAgent.removeListener(this);
|
||||
if (mContextMenuHandle.get()) mContextMenuHandle.get()->die();
|
||||
// <FS:PP> Group favorites / pinning
|
||||
if (mFavoritesChangedConnection.connected())
|
||||
{
|
||||
mFavoritesChangedConnection.disconnect();
|
||||
}
|
||||
// </FS:PP>
|
||||
}
|
||||
|
||||
void LLGroupList::enableForAgent(bool show_icons)
|
||||
|
|
@ -152,6 +199,11 @@ void LLGroupList::enableForAgent(bool show_icons)
|
|||
registrar.add("People.Groups.Action", boost::bind(&LLGroupList::onContextMenuItemClick, this, _2));
|
||||
enable_registrar.add("People.Groups.Enable", boost::bind(&LLGroupList::onContextMenuItemEnable, this, _2));
|
||||
|
||||
// <FS:PP> Group favorites / pinning
|
||||
mFavoritesChangedConnection = FSFavoriteGroups::getInstance()->setFavoritesChangedCallback(boost::bind(&LLGroupList::onFavoritesChanged, this));
|
||||
enable_registrar.add("People.Groups.Visible", boost::bind(&LLGroupList::onContextMenuItemVisible, this, _2));
|
||||
// </FS:PP>
|
||||
|
||||
LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_groups.xml",
|
||||
gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
|
||||
if(context_menu)
|
||||
|
|
@ -174,6 +226,13 @@ bool LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask)
|
|||
|
||||
if (mForAgent)
|
||||
{
|
||||
// <FS:PP> Group favorites / pinning
|
||||
LLPanel* selected_item = getSelectedItem();
|
||||
if (dynamic_cast<LLGroupListSeparator*>(selected_item))
|
||||
{
|
||||
return handled;
|
||||
}
|
||||
// </FS:PP>
|
||||
LLToggleableMenu* context_menu = mContextMenuHandle.get();
|
||||
if (context_menu && size() > 0)
|
||||
{
|
||||
|
|
@ -234,24 +293,53 @@ void LLGroupList::refresh()
|
|||
|
||||
clear();
|
||||
|
||||
// <FS:PP> Group favorites / pinning
|
||||
bool has_favorites = false;
|
||||
bool has_non_favorites = false;
|
||||
// </FS:PP>
|
||||
|
||||
for(S32 i = 0; i < count; ++i)
|
||||
{
|
||||
id = gAgent.mGroups.at(i).mID;
|
||||
const LLGroupData& group_data = gAgent.mGroups.at(i);
|
||||
if (have_filter && !findInsensitive(group_data.mName, mNameFilter))
|
||||
continue;
|
||||
addNewItem(id, group_data.mName, group_data.mInsigniaID, ADD_BOTTOM, group_data.mListInProfile);
|
||||
|
||||
// <FS:PP> Group favorites / pinning
|
||||
// addNewItem(id, group_data.mName, group_data.mInsigniaID, ADD_BOTTOM, group_data.mListInProfile);
|
||||
bool is_favorite = FSFavoriteGroups::getInstance()->isFavorite(id);
|
||||
if (is_favorite)
|
||||
{
|
||||
has_favorites = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
has_non_favorites = true;
|
||||
}
|
||||
addNewItem(id, group_data.mName, group_data.mInsigniaID, ADD_BOTTOM, group_data.mListInProfile, is_favorite);
|
||||
// </FS:PP>
|
||||
|
||||
}
|
||||
|
||||
// Sort the list.
|
||||
sort();
|
||||
|
||||
// <FS:PP> Group favorites / pinning
|
||||
if (has_favorites && has_non_favorites && !have_filter)
|
||||
{
|
||||
addFavoritesSeparator();
|
||||
}
|
||||
// </FS:PP>
|
||||
|
||||
// Add "none" to list at top if filter not set (what's the point of filtering "none"?).
|
||||
// but only if some real groups exists. EXT-4838
|
||||
if (!have_filter && count > 0 && mShowNone)
|
||||
{
|
||||
std::string loc_none = LLTrans::getString("GroupsNone");
|
||||
addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP);
|
||||
// <FS:PP> Group favorites / pinning
|
||||
// addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP);
|
||||
addNewItem(LLUUID::null, loc_none, LLUUID::null, ADD_TOP, true, false);
|
||||
// </FS:PP>
|
||||
}
|
||||
|
||||
selectItemByUUID(highlight_id);
|
||||
|
|
@ -298,13 +386,17 @@ void LLGroupList::setGroups(const std::map< std::string,LLUUID> group_list)
|
|||
// PRIVATE Section
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos, bool visible_in_profile)
|
||||
// <FS:PP> Group favorites / pinning
|
||||
// void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos, bool visible_in_profile)
|
||||
void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos, bool visible_in_profile, bool is_favorite)
|
||||
// </FS:PP>
|
||||
{
|
||||
LLGroupListItem* item = new LLGroupListItem(mForAgent, mShowIcons);
|
||||
|
||||
item->setGroupID(id);
|
||||
item->setName(name, mNameFilter);
|
||||
item->setGroupIconID(icon_id);
|
||||
item->setFavorite(is_favorite); // <FS:PP> Group favorites / pinning
|
||||
|
||||
item->getChildView("info_btn")->setVisible( false);
|
||||
item->getChildView("profile_btn")->setVisible( false);
|
||||
|
|
@ -390,6 +482,16 @@ bool LLGroupList::onContextMenuItemClick(const LLSD& userdata)
|
|||
LLUrlAction::copyURLToClipboard(LLSLURL("group", selected_group, "about").getSLURLString());
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
// <FS:PP> Group favorites / pinning
|
||||
else if (action == "favorite")
|
||||
{
|
||||
FSFavoriteGroups::getInstance()->addFavorite(selected_group);
|
||||
}
|
||||
else if (action == "unfavorite")
|
||||
{
|
||||
FSFavoriteGroups::getInstance()->removeFavorite(selected_group);
|
||||
}
|
||||
// </FS:PP>
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -412,9 +514,84 @@ bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata)
|
|||
if (userdata.asString() == "call")
|
||||
return real_group_selected && LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
|
||||
|
||||
// <FS:PP> Group favorites / pinning
|
||||
if (userdata.asString() == "favorite" || userdata.asString() == "unfavorite")
|
||||
return real_group_selected; // Just in case
|
||||
// </FS:PP>
|
||||
|
||||
return real_group_selected;
|
||||
}
|
||||
|
||||
// <FS:PP> Group favorites / pinning
|
||||
bool LLGroupList::onContextMenuItemVisible(const LLSD& userdata)
|
||||
{
|
||||
std::string action = userdata.asString();
|
||||
LLUUID selected_group_id = getSelectedUUID();
|
||||
|
||||
if (action == "favorite")
|
||||
{
|
||||
return selected_group_id.notNull() && !FSFavoriteGroups::getInstance()->isFavorite(selected_group_id);
|
||||
}
|
||||
else if (action == "unfavorite")
|
||||
{
|
||||
return selected_group_id.notNull() && FSFavoriteGroups::getInstance()->isFavorite(selected_group_id);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLGroupList::onFavoritesChanged()
|
||||
{
|
||||
setDirty();
|
||||
}
|
||||
|
||||
void LLGroupList::refreshFavorites()
|
||||
{
|
||||
setDirty();
|
||||
}
|
||||
|
||||
void LLGroupList::addFavoritesSeparator()
|
||||
{
|
||||
// Find the position to insert the separator (after the last favorite)
|
||||
std::vector<LLPanel*> items;
|
||||
getItems(items);
|
||||
|
||||
// Count favorite items to find where separator should go
|
||||
S32 favorite_count = 0;
|
||||
for (auto* panel : items)
|
||||
{
|
||||
LLGroupListItem* item = dynamic_cast<LLGroupListItem*>(panel);
|
||||
if (item && item->isFavorite())
|
||||
{
|
||||
++favorite_count;
|
||||
}
|
||||
}
|
||||
|
||||
if (favorite_count > 0)
|
||||
{
|
||||
LLGroupListSeparator* separator = new LLGroupListSeparator();
|
||||
static const LLUUID SEPARATOR_UUID("00000000-0000-0000-0000-000000000001");
|
||||
addItem(separator, SEPARATOR_UUID, ADD_BOTTOM, false);
|
||||
sort();
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* LLGroupListSeparator implementation */
|
||||
/************************************************************************/
|
||||
|
||||
LLGroupListSeparator::LLGroupListSeparator()
|
||||
: LLPanel()
|
||||
{
|
||||
buildFromFile("panel_group_list_separator.xml");
|
||||
}
|
||||
|
||||
bool LLGroupListSeparator::postBuild()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// </FS:PP>
|
||||
|
||||
/************************************************************************/
|
||||
/* LLGroupListItem implementation */
|
||||
/************************************************************************/
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@
|
|||
|
||||
#include "llgroupmgr.h"
|
||||
|
||||
#include <boost/signals2.hpp> // <FS:PP> Group favorites / pinning
|
||||
|
||||
/**
|
||||
* Auto-updating list of agent groups.
|
||||
*
|
||||
|
|
@ -72,14 +74,22 @@ public:
|
|||
|
||||
LLToggleableMenu* getContextMenu() const { return mContextMenuHandle.get(); }
|
||||
|
||||
void refreshFavorites(); // <FS:PP> Group favorites / pinning
|
||||
|
||||
private:
|
||||
void setDirty(bool val = true) { mDirty = val; }
|
||||
void refresh();
|
||||
void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos = ADD_BOTTOM, bool visible_in_profile = true);
|
||||
// <FS:PP> Group favorites / pinning
|
||||
// void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos = ADD_BOTTOM, bool visible_in_profile = true);
|
||||
void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos = ADD_BOTTOM, bool visible_in_profile = true, bool is_favorite = false);
|
||||
void addFavoritesSeparator();
|
||||
void onFavoritesChanged();
|
||||
// </FS:PP>
|
||||
bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); // called on agent group list changes
|
||||
|
||||
bool onContextMenuItemClick(const LLSD& userdata);
|
||||
bool onContextMenuItemEnable(const LLSD& userdata);
|
||||
bool onContextMenuItemVisible(const LLSD& userdata); // <FS:PP> Group favorites / pinning
|
||||
|
||||
LLHandle<LLToggleableMenu> mContextMenuHandle;
|
||||
|
||||
|
|
@ -91,12 +101,29 @@ private:
|
|||
bool mShowNone;
|
||||
typedef std::map< std::string,LLUUID> group_map_t;
|
||||
group_map_t mGroups;
|
||||
|
||||
boost::signals2::connection mFavoritesChangedConnection; // <FS:PP> Group favorites / pinning
|
||||
};
|
||||
|
||||
class LLButton;
|
||||
class LLGroupIconCtrl;
|
||||
class LLTextBox;
|
||||
|
||||
// <FS:PP> Group favorites / pinning
|
||||
class LLGroupListSeparator : public LLPanel
|
||||
{
|
||||
public:
|
||||
LLGroupListSeparator();
|
||||
/*virtual*/ bool postBuild();
|
||||
// Ignore all mouse interactions on the separator
|
||||
/*virtual*/ bool handleMouseDown(S32 x, S32 y, MASK mask) { return true; }
|
||||
/*virtual*/ bool handleMouseUp(S32 x, S32 y, MASK mask) { return true; }
|
||||
/*virtual*/ bool handleRightMouseDown(S32 x, S32 y, MASK mask) { return true; }
|
||||
/*virtual*/ bool handleRightMouseUp(S32 x, S32 y, MASK mask) { return true; }
|
||||
/*virtual*/ bool handleDoubleClick(S32 x, S32 y, MASK mask) { return true; }
|
||||
};
|
||||
// </FS:PP>
|
||||
|
||||
class LLGroupListItem : public LLPanel
|
||||
, public LLGroupMgrObserver
|
||||
{
|
||||
|
|
@ -110,11 +137,13 @@ public:
|
|||
|
||||
const LLUUID& getGroupID() const { return mGroupID; }
|
||||
const std::string& getGroupName() const { return mGroupName; }
|
||||
bool isFavorite() const { return mIsFavorite; } // <FS:PP> Group favorites / pinning
|
||||
|
||||
void setName(const std::string& name, const std::string& highlight = LLStringUtil::null);
|
||||
void setGroupID(const LLUUID& group_id);
|
||||
void setGroupIconID(const LLUUID& group_icon_id);
|
||||
void setGroupIconVisible(bool visible);
|
||||
void setFavorite(bool favorite) { mIsFavorite = favorite; } // <FS:PP> Group favorites / pinning
|
||||
|
||||
virtual void changed(LLGroupChange gc);
|
||||
|
||||
|
|
@ -137,6 +166,7 @@ private:
|
|||
|
||||
std::string mGroupName;
|
||||
bool mForAgent;
|
||||
bool mIsFavorite{ false }; // <FS:PP> Group favorites / pinning
|
||||
LLStyle::Params mGroupNameStyle;
|
||||
|
||||
S32 mIconWidth;
|
||||
|
|
|
|||
|
|
@ -233,6 +233,7 @@
|
|||
#include "fscommon.h"
|
||||
#include "fscorehttputil.h"
|
||||
#include "fsdata.h"
|
||||
#include "fsfavoritegroups.h" // <FS:PP> Group favorites / pinning
|
||||
#include "fsfloatercontacts.h"
|
||||
#include "fsfloaterimcontainer.h"
|
||||
#include "fsfloaternearbychat.h"
|
||||
|
|
@ -3315,6 +3316,10 @@ bool idle_startup()
|
|||
// Clean up the userauth stuff.
|
||||
// LLUserAuth::getInstance()->reset();
|
||||
|
||||
// <FS:PP> Group favorites / pinning
|
||||
FSFavoriteGroups::getInstance()->loadFavorites();
|
||||
// </FS:PP>
|
||||
|
||||
LLStartUp::setStartupState( STATE_STARTED );
|
||||
do_startup_frame();
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,12 @@
|
|||
<string
|
||||
name="no_groups_msg"
|
||||
value="Looking for Groups to join? Try [secondlife:///app/search/groups Search]." />
|
||||
<string
|
||||
name="favorite_label"
|
||||
value="Pin" />
|
||||
<string
|
||||
name="unfavorite_label"
|
||||
value="Unpin" />
|
||||
<tab_container
|
||||
follows="all"
|
||||
height="390"
|
||||
|
|
|
|||
|
|
@ -52,6 +52,32 @@
|
|||
function="People.Groups.Enable"
|
||||
parameter="call" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Pin group"
|
||||
name="Favorite">
|
||||
<menu_item_call.on_click
|
||||
function="People.Groups.Action"
|
||||
parameter="favorite" />
|
||||
<menu_item_call.on_enable
|
||||
function="People.Groups.Enable"
|
||||
parameter="favorite" />
|
||||
<menu_item_call.on_visible
|
||||
function="People.Groups.Visible"
|
||||
parameter="favorite" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Unpin group"
|
||||
name="Unfavorite">
|
||||
<menu_item_call.on_click
|
||||
function="People.Groups.Action"
|
||||
parameter="unfavorite" />
|
||||
<menu_item_call.on_enable
|
||||
function="People.Groups.Enable"
|
||||
parameter="unfavorite" />
|
||||
<menu_item_call.on_visible
|
||||
function="People.Groups.Visible"
|
||||
parameter="unfavorite" />
|
||||
</menu_item_call>
|
||||
<menu_item_separator />
|
||||
<menu_item_call
|
||||
label="Leave"
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
<button
|
||||
top="2"
|
||||
follows="top|right"
|
||||
height="22"
|
||||
height="20"
|
||||
label="IM/Call"
|
||||
layout="topleft"
|
||||
right="-1"
|
||||
|
|
@ -59,7 +59,7 @@
|
|||
<button
|
||||
top_delta="25"
|
||||
follows="top|right"
|
||||
height="22"
|
||||
height="20"
|
||||
label="Profile"
|
||||
layout="topleft"
|
||||
name="info_btn"
|
||||
|
|
@ -67,7 +67,7 @@
|
|||
<button
|
||||
top_delta="25"
|
||||
follows="top|right"
|
||||
height="22"
|
||||
height="20"
|
||||
label="Group Titles"
|
||||
layout="topleft"
|
||||
name="titles_btn"
|
||||
|
|
@ -75,7 +75,7 @@
|
|||
<button
|
||||
top_delta="25"
|
||||
follows="top|right"
|
||||
height="22"
|
||||
height="20"
|
||||
label="Activate"
|
||||
layout="topleft"
|
||||
name="activate_btn"
|
||||
|
|
@ -83,15 +83,24 @@
|
|||
<button
|
||||
top_delta="25"
|
||||
follows="top|right"
|
||||
height="22"
|
||||
height="20"
|
||||
label="Pin"
|
||||
layout="topleft"
|
||||
name="favorite_btn"
|
||||
tool_tip="Add or remove group from favorites"
|
||||
width="80" />
|
||||
<button
|
||||
top_delta="25"
|
||||
follows="top|right"
|
||||
height="20"
|
||||
label="Leave"
|
||||
layout="topleft"
|
||||
name="leave_btn"
|
||||
width="80" />
|
||||
<button
|
||||
top_delta="35"
|
||||
top_delta="31"
|
||||
follows="top|right"
|
||||
height="22"
|
||||
height="20"
|
||||
label="Create..."
|
||||
layout="topleft"
|
||||
name="create_btn"
|
||||
|
|
@ -99,7 +108,7 @@
|
|||
<button
|
||||
top_delta="25"
|
||||
follows="top|right"
|
||||
height="22"
|
||||
height="20"
|
||||
label="Search..."
|
||||
layout="topleft"
|
||||
name="search_btn"
|
||||
|
|
@ -107,7 +116,7 @@
|
|||
<button
|
||||
top_delta="25"
|
||||
follows="top|right"
|
||||
height="22"
|
||||
height="20"
|
||||
label="Invite..."
|
||||
layout="topleft"
|
||||
name="invite_btn"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<panel
|
||||
follows="left|top|right"
|
||||
height="10"
|
||||
layout="topleft"
|
||||
left="0"
|
||||
name="group_list_separator"
|
||||
top="0"
|
||||
width="300">
|
||||
<view_border
|
||||
bevel_style="none"
|
||||
follows="left|right|top"
|
||||
height="1"
|
||||
layout="topleft"
|
||||
left="5"
|
||||
name="separator_line"
|
||||
right="-5"
|
||||
top="5" />
|
||||
</panel>
|
||||
|
||||
|
|
@ -3,6 +3,8 @@
|
|||
<string name="no_friends" value="Brak znajomych" />
|
||||
<string name="no_filtered_groups_msg" value="Nie znaleziono grup zawierających frazę "[SEARCH_TERM]"." />
|
||||
<string name="no_groups_msg" value="Szukasz grup, do jakich można by dołączyć? Spróbuj [secondlife:///app/search/groups wyszukać]." />
|
||||
<string name="favorite_label" value="Przypnij" />
|
||||
<string name="unfavorite_label" value="Odepnij" />
|
||||
<tab_container name="friends_and_groups">
|
||||
<panel label="Znajomi" name="friends_panel" />
|
||||
<panel label="Grupy" name="groups_panel" />
|
||||
|
|
|
|||
|
|
@ -5,5 +5,7 @@
|
|||
<menu_item_call label="Kopiuj SLurl do schowka" name="Copy SLurl to clipboard"/>
|
||||
<menu_item_call label="Czat" name="Chat"/>
|
||||
<menu_item_call label="Rozmowa głosowa" name="Call"/>
|
||||
<menu_item_call label="Przypnij grupę" name="Favorite" />
|
||||
<menu_item_call label="Odepnij grupę" name="Unfavorite" />
|
||||
<menu_item_call label="Opuść" name="Leave"/>
|
||||
</toggleable_menu>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
<button label="Profil" name="info_btn"/>
|
||||
<button label="Tytuły grup" name="titles_btn"/>
|
||||
<button label="Aktywuj" name="activate_btn"/>
|
||||
<button label="Przypnij" name="favorite_btn" tool_tip="Dodaj lub usuń grupę z ulubionych" />
|
||||
<button label="Opuść" name="leave_btn"/>
|
||||
<button label="Utwórz..." name="create_btn"/>
|
||||
<button label="Szukaj..." name="search_btn"/>
|
||||
|
|
|
|||
Loading…
Reference in New Issue