mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
215 lines
6.2 KiB
C++
215 lines
6.2 KiB
C++
/*
|
|
Copyright © 2014-2018 by The qTox Project Contributors
|
|
|
|
This file is part of qTox, a Qt-based graphical interface for Tox.
|
|
|
|
qTox is libre software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
qTox 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "group.h"
|
|
#include "friend.h"
|
|
#include "src/core/contactid.h"
|
|
#include "src/core/core.h"
|
|
#include "src/core/coreav.h"
|
|
#include "src/core/groupid.h"
|
|
#include "src/core/toxpk.h"
|
|
#include "src/friendlist.h"
|
|
#include "src/persistence/settings.h"
|
|
#include "src/widget/form/groupchatform.h"
|
|
#include "src/widget/groupwidget.h"
|
|
#include <QDebug>
|
|
|
|
static const int MAX_GROUP_TITLE_LENGTH = 128;
|
|
|
|
Group::Group(int groupId, const GroupId persistentGroupId, const QString& name, bool isAvGroupchat,
|
|
const QString& selfName, ICoreGroupQuery& groupQuery, ICoreIdHandler& idHandler)
|
|
: selfName{selfName}
|
|
, title{name}
|
|
, toxGroupNum(groupId)
|
|
, groupId{persistentGroupId}
|
|
, avGroupchat{isAvGroupchat}
|
|
, groupQuery(groupQuery)
|
|
, idHandler(idHandler)
|
|
{
|
|
// in groupchats, we only notify on messages containing your name <-- dumb
|
|
// sound notifications should be on all messages, but system popup notification
|
|
// on naming is appropriate
|
|
hasNewMessages = 0;
|
|
userWasMentioned = 0;
|
|
regeneratePeerList();
|
|
}
|
|
|
|
void Group::setName(const QString& newTitle)
|
|
{
|
|
const QString shortTitle = newTitle.left(MAX_GROUP_TITLE_LENGTH);
|
|
if (!shortTitle.isEmpty() && title != shortTitle) {
|
|
title = shortTitle;
|
|
emit displayedNameChanged(title);
|
|
emit titleChangedByUser(title);
|
|
emit titleChanged(selfName, title);
|
|
}
|
|
}
|
|
|
|
void Group::setTitle(const QString& author, const QString& newTitle)
|
|
{
|
|
const QString shortTitle = newTitle.left(MAX_GROUP_TITLE_LENGTH);
|
|
if (!shortTitle.isEmpty() && title != shortTitle) {
|
|
title = shortTitle;
|
|
emit displayedNameChanged(title);
|
|
emit titleChanged(author, title);
|
|
}
|
|
}
|
|
|
|
QString Group::getName() const
|
|
{
|
|
return title;
|
|
}
|
|
|
|
QString Group::getDisplayedName() const
|
|
{
|
|
return getName();
|
|
}
|
|
|
|
void Group::regeneratePeerList()
|
|
{
|
|
// NOTE: there's a bit of a race here. Core emits a signal for both groupPeerlistChanged and
|
|
// groupPeerNameChanged back-to-back when a peer joins our group. If we get both before we
|
|
// process this slot, core->getGroupPeerNames will contain the new peer name, and we'll ignore
|
|
// the name changed signal, and emit a single userJoined with the correct name. But, if we
|
|
// receive the name changed signal a little later, we will emit userJoined before we have their
|
|
// username, using just their ToxPk, then shortly after emit another peerNameChanged signal.
|
|
// This can cause double-updated to UI and chatlog, but is unavoidable given the API of toxcore.
|
|
QStringList peers = groupQuery.getGroupPeerNames(toxGroupNum);
|
|
const auto oldPeerNames = peerDisplayNames;
|
|
peerDisplayNames.clear();
|
|
const int nPeers = peers.size();
|
|
for (int i = 0; i < nPeers; ++i) {
|
|
const auto pk = groupQuery.getGroupPeerPk(toxGroupNum, i);
|
|
if (pk == idHandler.getSelfPublicKey()) {
|
|
peerDisplayNames[pk] = idHandler.getUsername();
|
|
} else {
|
|
peerDisplayNames[pk] = FriendList::decideNickname(pk, peers[i]);
|
|
}
|
|
}
|
|
for (const auto& pk : oldPeerNames.keys()) {
|
|
if (!peerDisplayNames.contains(pk)) {
|
|
emit userLeft(pk, oldPeerNames.value(pk));
|
|
stopAudioOfDepartedPeers(pk);
|
|
}
|
|
}
|
|
for (const auto& pk : peerDisplayNames.keys()) {
|
|
if (!oldPeerNames.contains(pk)) {
|
|
emit userJoined(pk, peerDisplayNames.value(pk));
|
|
}
|
|
}
|
|
for (const auto& pk : peerDisplayNames.keys()) {
|
|
if (oldPeerNames.contains(pk) && oldPeerNames.value(pk) != peerDisplayNames.value(pk)) {
|
|
emit peerNameChanged(pk, oldPeerNames.value(pk), peerDisplayNames.value(pk));
|
|
}
|
|
}
|
|
if (oldPeerNames.size() != nPeers) {
|
|
emit numPeersChanged(nPeers);
|
|
}
|
|
}
|
|
|
|
void Group::updateUsername(ToxPk pk, const QString newName)
|
|
{
|
|
const QString displayName = FriendList::decideNickname(pk, newName);
|
|
assert(peerDisplayNames.contains(pk));
|
|
if (peerDisplayNames[pk] != displayName) {
|
|
// there could be no actual change even if their username changed due to an alias being set
|
|
const auto oldName = peerDisplayNames[pk];
|
|
peerDisplayNames[pk] = displayName;
|
|
emit peerNameChanged(pk, oldName, displayName);
|
|
}
|
|
}
|
|
|
|
bool Group::isAvGroupchat() const
|
|
{
|
|
return avGroupchat;
|
|
}
|
|
|
|
uint32_t Group::getId() const
|
|
{
|
|
return toxGroupNum;
|
|
}
|
|
|
|
const GroupId& Group::getPersistentId() const
|
|
{
|
|
return groupId;
|
|
}
|
|
|
|
int Group::getPeersCount() const
|
|
{
|
|
return peerDisplayNames.size();
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the PKs and names of all peers
|
|
* @return PKs and names of all peers, including our own PK and name
|
|
*/
|
|
const QMap<ToxPk, QString>& Group::getPeerList() const
|
|
{
|
|
return peerDisplayNames;
|
|
}
|
|
|
|
void Group::setEventFlag(bool f)
|
|
{
|
|
hasNewMessages = f;
|
|
}
|
|
|
|
bool Group::getEventFlag() const
|
|
{
|
|
return hasNewMessages;
|
|
}
|
|
|
|
void Group::setMentionedFlag(bool f)
|
|
{
|
|
userWasMentioned = f;
|
|
}
|
|
|
|
bool Group::getMentionedFlag() const
|
|
{
|
|
return userWasMentioned;
|
|
}
|
|
|
|
QString Group::resolveToxId(const ToxPk& id) const
|
|
{
|
|
auto it = peerDisplayNames.find(id);
|
|
|
|
if (it != peerDisplayNames.end()) {
|
|
return *it;
|
|
}
|
|
|
|
return QString();
|
|
}
|
|
|
|
void Group::setSelfName(const QString& name)
|
|
{
|
|
selfName = name;
|
|
}
|
|
|
|
QString Group::getSelfName() const
|
|
{
|
|
return selfName;
|
|
}
|
|
|
|
void Group::stopAudioOfDepartedPeers(const ToxPk& peerPk)
|
|
{
|
|
if (avGroupchat) {
|
|
Core* core = Core::getInstance();
|
|
core->getAv()->invalidateGroupCallPeerSource(toxGroupNum, peerPk);
|
|
}
|
|
}
|