// Copyright 2005-2019 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 . #include "murmur_pch.h" #include "Channel.h" #include "User.h" #include "Group.h" #include "ACL.h" #ifdef MUMBLE QHash 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(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::allLinks() { QSet seen; seen.insert(this); if (qhLinks.isEmpty()) return seen; QStack 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::allChildren() { QSet seen; if (! qlChannels.isEmpty()) { QStack 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; }