mirror of
https://github.com/mumble-voip/mumble.git
synced 2025-10-26 11:19:16 +00:00
219 lines
4.2 KiB
C++
219 lines
4.2 KiB
C++
// Copyright 2005-2018 The Mumble Developers. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license
|
|
// that can be found in the LICENSE file at the root of the
|
|
// Mumble source tree or at <https://www.mumble.info/LICENSE>.
|
|
|
|
#include "murmur_pch.h"
|
|
|
|
#include "Channel.h"
|
|
#include "User.h"
|
|
#include "Group.h"
|
|
#include "ACL.h"
|
|
|
|
#ifdef MUMBLE
|
|
QHash<int, Channel *> Channel::c_qhChannels;
|
|
QReadWriteLock Channel::c_qrwlChannels;
|
|
#endif
|
|
|
|
Channel::Channel(int id, const QString &name, QObject *p) : QObject(p) {
|
|
iId = id;
|
|
iPosition = 0;
|
|
qsName = name;
|
|
bInheritACL = true;
|
|
uiMaxUsers = 0;
|
|
bTemporary = false;
|
|
cParent = qobject_cast<Channel *>(p);
|
|
if (cParent)
|
|
cParent->addChannel(this);
|
|
#ifdef MUMBLE
|
|
uiPermissions = 0;
|
|
bFiltered = false;
|
|
#endif
|
|
}
|
|
|
|
Channel::~Channel() {
|
|
if (cParent)
|
|
cParent->removeChannel(this);
|
|
|
|
foreach(Channel *c, qlChannels)
|
|
delete c;
|
|
|
|
foreach(ChanACL *acl, qlACL)
|
|
delete acl;
|
|
foreach(Group *g, qhGroups)
|
|
delete g;
|
|
foreach(Channel *l, qhLinks.keys())
|
|
unlink(l);
|
|
|
|
Q_ASSERT(qlChannels.count() == 0);
|
|
Q_ASSERT(children().count() == 0);
|
|
}
|
|
|
|
#ifdef MUMBLE
|
|
Channel *Channel::get(int id) {
|
|
QReadLocker lock(&c_qrwlChannels);
|
|
return c_qhChannels.value(id);
|
|
}
|
|
|
|
Channel *Channel::add(int id, const QString &name) {
|
|
QWriteLocker lock(&c_qrwlChannels);
|
|
|
|
if (c_qhChannels.contains(id))
|
|
return NULL;
|
|
|
|
Channel *c = new Channel(id, name, NULL);
|
|
c_qhChannels.insert(id, c);
|
|
return c;
|
|
}
|
|
|
|
void Channel::remove(Channel *c) {
|
|
QWriteLocker lock(&c_qrwlChannels);
|
|
c_qhChannels.remove(c->iId);
|
|
}
|
|
#endif
|
|
|
|
bool Channel::lessThan(const Channel *first, const Channel *second) {
|
|
if ((first->iPosition != second->iPosition) && (first->cParent == second->cParent))
|
|
return first->iPosition < second->iPosition;
|
|
else
|
|
return QString::localeAwareCompare(first->qsName, second->qsName) < 0;
|
|
}
|
|
|
|
bool Channel::isLinked(Channel *l) const {
|
|
return ((l == this) || qhLinks.contains(l));
|
|
}
|
|
|
|
void Channel::link(Channel *l) {
|
|
if (qsPermLinks.contains(l))
|
|
return;
|
|
qsPermLinks.insert(l);
|
|
qhLinks[l]++;
|
|
l->qsPermLinks.insert(this);
|
|
l->qhLinks[this]++;
|
|
}
|
|
|
|
void Channel::unlink(Channel *l) {
|
|
if (l) {
|
|
qsPermLinks.remove(l);
|
|
qhLinks.remove(l);
|
|
l->qsPermLinks.remove(this);
|
|
l->qhLinks.remove(this);
|
|
} else {
|
|
foreach(Channel *c, qhLinks.keys())
|
|
unlink(c);
|
|
}
|
|
}
|
|
|
|
QSet<Channel *> Channel::allLinks() {
|
|
QSet<Channel *> seen;
|
|
seen.insert(this);
|
|
if (qhLinks.isEmpty())
|
|
return seen;
|
|
|
|
QStack<Channel *> stack;
|
|
stack.push(this);
|
|
|
|
while (! stack.isEmpty()) {
|
|
Channel *lnk = stack.pop();
|
|
foreach(Channel *l, lnk->qhLinks.keys()) {
|
|
if (! seen.contains(l)) {
|
|
seen.insert(l);
|
|
stack.push(l);
|
|
}
|
|
}
|
|
}
|
|
return seen;
|
|
}
|
|
|
|
QSet<Channel *> Channel::allChildren() {
|
|
QSet<Channel *> seen;
|
|
if (! qlChannels.isEmpty()) {
|
|
QStack<Channel *> stack;
|
|
stack.push(this);
|
|
|
|
while (! stack.isEmpty()) {
|
|
Channel *c = stack.pop();
|
|
foreach(Channel *chld, c->qlChannels) {
|
|
seen.insert(chld);
|
|
if (! chld->qlChannels.isEmpty())
|
|
stack.append(chld);
|
|
}
|
|
}
|
|
}
|
|
return seen;
|
|
}
|
|
|
|
void Channel::addChannel(Channel *c) {
|
|
c->cParent = this;
|
|
c->setParent(this);
|
|
qlChannels << c;
|
|
}
|
|
|
|
void Channel::removeChannel(Channel *c) {
|
|
c->cParent = NULL;
|
|
c->setParent(NULL);
|
|
qlChannels.removeAll(c);
|
|
}
|
|
|
|
void Channel::addUser(User *p) {
|
|
if (p->cChannel)
|
|
p->cChannel->removeUser(p);
|
|
p->cChannel = this;
|
|
qlUsers << p;
|
|
}
|
|
|
|
void Channel::removeUser(User *p) {
|
|
qlUsers.removeAll(p);
|
|
}
|
|
|
|
Channel::operator QString() const {
|
|
return QString::fromLatin1("%1[%2:%3%4]").arg(qsName,
|
|
QString::number(iId),
|
|
QString::number(cParent ? cParent->iId : -1),
|
|
bTemporary ? QLatin1String("*") : QLatin1String(""));
|
|
}
|
|
|
|
size_t Channel::getLevel() const {
|
|
size_t i = 0;
|
|
|
|
const Channel *c = this;
|
|
while (c->cParent) {
|
|
c = c->cParent;
|
|
++i;
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
size_t Channel::getDepth() const {
|
|
if(qlChannels.empty()) {
|
|
return 0;
|
|
}
|
|
|
|
size_t result = 0;
|
|
foreach(Channel *child, qlChannels) {
|
|
result = qMax(result, child->getDepth() + 1);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
QString Channel::getPath() const {
|
|
QString out;
|
|
|
|
const Channel *tmp = this;
|
|
while (tmp->cParent) {
|
|
// Skip the root channel.
|
|
if (tmp->iId == 0) {
|
|
break;
|
|
}
|
|
|
|
out.prepend(QString::fromLatin1("/"));
|
|
out.prepend(tmp->qsName);
|
|
|
|
tmp = tmp->cParent;
|
|
}
|
|
|
|
return out;
|
|
}
|