Permission model
Add a model for managing permissions (power levels) in rooms. This gets rid of a whole bunch of boiler plate in NeoChat and as a bonus makes it easy to add a feature to allow setting the permission level for any event.
This commit is contained in:
@@ -181,6 +181,10 @@ add_library(neochat STATIC
|
||||
jobs/neochatadd3pidjob.h
|
||||
identityserverhelper.cpp
|
||||
identityserverhelper.h
|
||||
enums/powerlevel.cpp
|
||||
enums/powerlevel.h
|
||||
models/permissionsmodel.cpp
|
||||
models/permissionsmodel.h
|
||||
)
|
||||
|
||||
set_source_files_properties(qml/OsmLocationPlugin.qml PROPERTIES
|
||||
|
||||
107
src/enums/powerlevel.cpp
Normal file
107
src/enums/powerlevel.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#include "powerlevel.h"
|
||||
|
||||
QString PowerLevel::nameForLevel(Level level)
|
||||
{
|
||||
switch (level) {
|
||||
case PowerLevel::Member:
|
||||
return i18n("Member");
|
||||
case PowerLevel::Moderator:
|
||||
return i18n("Moderator");
|
||||
case PowerLevel::Admin:
|
||||
return i18n("Admin");
|
||||
case PowerLevel::Mute:
|
||||
return i18n("Mute");
|
||||
case PowerLevel::Custom:
|
||||
return i18n("Custom");
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
int PowerLevel::valueForLevel(Level level)
|
||||
{
|
||||
switch (level) {
|
||||
case PowerLevel::Member:
|
||||
return 0;
|
||||
case PowerLevel::Moderator:
|
||||
return 50;
|
||||
case PowerLevel::Admin:
|
||||
return 100;
|
||||
case PowerLevel::Mute:
|
||||
return -1;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
PowerLevel::Level PowerLevel::levelForValue(int value)
|
||||
{
|
||||
switch (value) {
|
||||
case 0:
|
||||
return PowerLevel::Member;
|
||||
case 50:
|
||||
return PowerLevel::Moderator;
|
||||
case 100:
|
||||
return PowerLevel::Admin;
|
||||
case -1:
|
||||
return PowerLevel::Mute;
|
||||
default:
|
||||
return PowerLevel::Custom;
|
||||
}
|
||||
}
|
||||
|
||||
PowerLevelModel::PowerLevelModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool PowerLevelModel::showMute() const
|
||||
{
|
||||
return m_showMute;
|
||||
}
|
||||
|
||||
void PowerLevelModel::setShowMute(bool showMute)
|
||||
{
|
||||
if (showMute == m_showMute) {
|
||||
return;
|
||||
}
|
||||
m_showMute = showMute;
|
||||
Q_EMIT showMuteChanged();
|
||||
}
|
||||
|
||||
QVariant PowerLevelModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
return {};
|
||||
}
|
||||
if (index.row() >= rowCount()) {
|
||||
qDebug() << "PowerLevelModel, something's wrong: index.row() >= m_rules.count()";
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto level = static_cast<PowerLevel::Level>(index.row());
|
||||
if (role == NameRole) {
|
||||
return i18nc("%1 is the name of the power level, e.g. admin and %2 is the value that represents.",
|
||||
"%1 (%2)",
|
||||
PowerLevel::nameForLevel(level),
|
||||
PowerLevel::valueForLevel(level));
|
||||
}
|
||||
if (role == ValueRole) {
|
||||
return PowerLevel::valueForLevel(level);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
int PowerLevelModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return PowerLevel::NUMLevels - (m_showMute ? 0 : 1);
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> PowerLevelModel::roleNames() const
|
||||
{
|
||||
return {{NameRole, "name"}, {ValueRole, "value"}};
|
||||
}
|
||||
110
src/enums/powerlevel.h
Normal file
110
src/enums/powerlevel.h
Normal file
@@ -0,0 +1,110 @@
|
||||
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QObject>
|
||||
#include <QQmlEngine>
|
||||
|
||||
#include <KLocalizedString>
|
||||
|
||||
/**
|
||||
* @class PowerLevel
|
||||
*
|
||||
* This class is designed to define the PowerLevel enumeration.
|
||||
*/
|
||||
class PowerLevel : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_UNCREATABLE("")
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief The type of delegate that is needed for the event.
|
||||
*
|
||||
* @note While similar this is not the matrix event or message type. This is
|
||||
* to tell a QML ListView what delegate to show for each event. So while
|
||||
* similar to the spec it is not the same.
|
||||
*/
|
||||
enum Level {
|
||||
Member, /**< A basic member. */
|
||||
Moderator, /**< A moderator with enhanced powers. */
|
||||
Admin, /**< The highest power level in the room. */
|
||||
Mute, /**< The level to remove posting privileges. */
|
||||
NUMLevels,
|
||||
Custom, /**< A non-standard value. Intentionally after NUMLevels so it doesn't appear in the model. */
|
||||
};
|
||||
Q_ENUM(Level);
|
||||
|
||||
/**
|
||||
* @brief Return a string representation of the enum value.
|
||||
*/
|
||||
static QString nameForLevel(Level level);
|
||||
|
||||
/**
|
||||
* @brief Return the integer representation of the enum value.
|
||||
*/
|
||||
static int valueForLevel(Level level);
|
||||
|
||||
/**
|
||||
* @brief Return the enum value for the given integer power level.
|
||||
*/
|
||||
static Level levelForValue(int value);
|
||||
};
|
||||
|
||||
/**
|
||||
* @class PowerLevelModel
|
||||
*
|
||||
* A model visualize the allowed power levels.
|
||||
*/
|
||||
class PowerLevelModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
Q_PROPERTY(bool showMute READ showMute WRITE setShowMute NOTIFY showMuteChanged)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Defines the model roles.
|
||||
*/
|
||||
enum Roles {
|
||||
NameRole = Qt::DisplayRole, /**< The power level name. */
|
||||
ValueRole, /**< The power level value. */
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
explicit PowerLevelModel(QObject *parent = nullptr);
|
||||
|
||||
[[nodiscard]] bool showMute() const;
|
||||
void setShowMute(bool showMute);
|
||||
|
||||
/**
|
||||
* @brief Get the given role value at the given index.
|
||||
*
|
||||
* @sa QAbstractItemModel::data
|
||||
*/
|
||||
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
/**
|
||||
* @brief Number of rows in the model.
|
||||
*
|
||||
* @sa QAbstractItemModel::rowCount
|
||||
*/
|
||||
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
/**
|
||||
* @brief Returns a mapping from Role enum values to role names.
|
||||
*
|
||||
* @sa Roles, QAbstractItemModel::roleNames()
|
||||
*/
|
||||
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void showMuteChanged();
|
||||
|
||||
private:
|
||||
bool m_showMute = true;
|
||||
};
|
||||
254
src/models/permissionsmodel.cpp
Normal file
254
src/models/permissionsmodel.cpp
Normal file
@@ -0,0 +1,254 @@
|
||||
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#include "permissionsmodel.h"
|
||||
#include "powerlevel.h"
|
||||
|
||||
#include <Quotient/events/roompowerlevelsevent.h>
|
||||
|
||||
#include <KLazyLocalizedString>
|
||||
|
||||
static const QStringList defaultPermissions = {
|
||||
QStringLiteral("users_default"),
|
||||
QStringLiteral("state_default"),
|
||||
QStringLiteral("events_default"),
|
||||
QStringLiteral("invite"),
|
||||
QStringLiteral("kick"),
|
||||
QStringLiteral("ban"),
|
||||
QStringLiteral("redact"),
|
||||
QStringLiteral("m.reaction"),
|
||||
QStringLiteral("m.room.redaction"),
|
||||
QStringLiteral("m.room.power_levels"),
|
||||
QStringLiteral("m.room.name"),
|
||||
QStringLiteral("m.room.avatar"),
|
||||
QStringLiteral("m.room.canonical_alias"),
|
||||
QStringLiteral("m.room.topic"),
|
||||
QStringLiteral("m.room.encryption"),
|
||||
QStringLiteral("m.room.history_visibility"),
|
||||
QStringLiteral("m.room.pinned_events"),
|
||||
QStringLiteral("m.room.tombstone"),
|
||||
QStringLiteral("m.room.server_acl"),
|
||||
QStringLiteral("m.space.child"),
|
||||
QStringLiteral("m.space.parent"),
|
||||
};
|
||||
|
||||
// Alternate name text for default permissions.
|
||||
static const QHash<QString, KLazyLocalizedString> defaultPermissionNames = {
|
||||
{QStringLiteral("users_default"), kli18nc("Room permission type", "Default user power level")},
|
||||
{QStringLiteral("state_default"), kli18nc("Room permission type", "Default power level to set the room state")},
|
||||
{QStringLiteral("events_default"), kli18nc("Room permission type", "Default power level to send messages")},
|
||||
{QStringLiteral("invite"), kli18nc("Room permission type", "Invite users")},
|
||||
{QStringLiteral("kick"), kli18nc("Room permission type", "Kick users")},
|
||||
{QStringLiteral("ban"), kli18nc("Room permission type", "Ban users")},
|
||||
{QStringLiteral("redact"), kli18nc("Room permission type", "Remove messages sent by other users")},
|
||||
{QStringLiteral("m.reaction"), kli18nc("Room permission type", "Send reactions")},
|
||||
{QStringLiteral("m.room.redaction"), kli18nc("Room permission type", "Remove their own messages")},
|
||||
{QStringLiteral("m.room.power_levels"), kli18nc("Room permission type", "Change user permissions")},
|
||||
{QStringLiteral("m.room.name"), kli18nc("Room permission type", "Change the room name")},
|
||||
{QStringLiteral("m.room.avatar"), kli18nc("Room permission type", "Change the room avatar")},
|
||||
{QStringLiteral("m.room.canonical_alias"), kli18nc("Room permission type", "Change the room canonical alias")},
|
||||
{QStringLiteral("m.room.topic"), kli18nc("Room permission type", "Change the room topic")},
|
||||
{QStringLiteral("m.room.encryption"), kli18nc("Room permission type", "Enable encryption for the room")},
|
||||
{QStringLiteral("m.room.history_visibility"), kli18nc("Room permission type", "Change the room history visibility")},
|
||||
{QStringLiteral("m.room.pinned_events"), kli18nc("Room permission type", "Set pinned events")},
|
||||
{QStringLiteral("m.room.tombstone"), kli18nc("Room permission type", "Upgrade the room")},
|
||||
{QStringLiteral("m.room.server_acl"), kli18nc("Room permission type", "Set the room server access control list (ACL)")},
|
||||
{QStringLiteral("m.space.child"), kli18nc("Room permission type", "Set the children of this space")},
|
||||
{QStringLiteral("m.space.parent"), kli18nc("Room permission type", "Set the parent space of this room")},
|
||||
};
|
||||
|
||||
// Subtitles for the default values.
|
||||
static const QHash<QString, KLazyLocalizedString> defaultSubtitles = {
|
||||
{QStringLiteral("users_default"), kli18nc("Room permission type", "This is the power level for all new users when joining the room")},
|
||||
{QStringLiteral("state_default"), kli18nc("Room permission type", "This is used for all state events that do not have their own entry here")},
|
||||
{QStringLiteral("events_default"), kli18nc("Room permission type", "This is used for all message events that do not have their own entry here")},
|
||||
};
|
||||
|
||||
// Permissions that should use the event default.
|
||||
static const QStringList eventPermissions = {
|
||||
QStringLiteral("m.room.message"),
|
||||
QStringLiteral("m.reaction"),
|
||||
QStringLiteral("m.room.redaction"),
|
||||
};
|
||||
|
||||
PermissionsModel::PermissionsModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
NeoChatRoom *PermissionsModel::room() const
|
||||
{
|
||||
return m_room;
|
||||
}
|
||||
|
||||
void PermissionsModel::setRoom(NeoChatRoom *room)
|
||||
{
|
||||
if (room == m_room) {
|
||||
return;
|
||||
}
|
||||
m_room = room;
|
||||
Q_EMIT roomChanged();
|
||||
|
||||
initializeModel();
|
||||
}
|
||||
|
||||
void PermissionsModel::initializeModel()
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
m_permissions.clear();
|
||||
|
||||
if (m_room == nullptr) {
|
||||
endResetModel();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto currentPowerLevelEvent = m_room->currentState().get<Quotient::RoomPowerLevelsEvent>();
|
||||
if (currentPowerLevelEvent == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_permissions.append(defaultPermissions);
|
||||
|
||||
for (const auto &event : currentPowerLevelEvent->events().keys()) {
|
||||
if (!m_permissions.contains(event)) {
|
||||
m_permissions += event;
|
||||
}
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QVariant PermissionsModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (m_room == nullptr || !index.isValid()) {
|
||||
return {};
|
||||
}
|
||||
if (index.row() >= rowCount()) {
|
||||
qDebug() << "PushRuleModel, something's wrong: index.row() >= m_rules.count()";
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto permission = m_permissions.value(index.row());
|
||||
if (role == NameRole) {
|
||||
if (defaultPermissionNames.keys().contains(permission)) {
|
||||
return defaultPermissionNames.value(permission).toString();
|
||||
}
|
||||
return permission;
|
||||
}
|
||||
if (role == SubtitleRole) {
|
||||
if (permission.startsWith(QLatin1String("m.")) && defaultPermissionNames.keys().contains(permission)) {
|
||||
return permission;
|
||||
}
|
||||
if (defaultSubtitles.contains(permission)) {
|
||||
return defaultSubtitles.value(permission).toString();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
if (role == TypeRole) {
|
||||
return permission;
|
||||
}
|
||||
if (role == LevelRole) {
|
||||
const auto level = powerLevel(permission);
|
||||
if (level.has_value()) {
|
||||
return *level;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
if (role == LevelNameRole) {
|
||||
const auto level = powerLevel(permission);
|
||||
if (level.has_value()) {
|
||||
return i18nc("%1 is the name of the power level, e.g. admin and %2 is the value that represents.",
|
||||
"%1 (%2)",
|
||||
PowerLevel::nameForLevel(PowerLevel::levelForValue(*level)),
|
||||
*level);
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
if (role == IsDefaultValueRole) {
|
||||
return permission.contains(QLatin1String("default"));
|
||||
}
|
||||
if (role == IsBasicPermissionRole) {
|
||||
return permission == QStringLiteral("invite") || permission == QStringLiteral("kick") || permission == QStringLiteral("ban")
|
||||
|| permission == QStringLiteral("redact");
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
int PermissionsModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return m_permissions.count();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> PermissionsModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
|
||||
roles[NameRole] = "name";
|
||||
roles[SubtitleRole] = "subtitle";
|
||||
roles[TypeRole] = "type";
|
||||
roles[LevelRole] = "level";
|
||||
roles[LevelNameRole] = "levelName";
|
||||
roles[IsDefaultValueRole] = "isDefaultValue";
|
||||
roles[IsBasicPermissionRole] = "isBasicPermission";
|
||||
return roles;
|
||||
}
|
||||
|
||||
std::optional<int> PermissionsModel::powerLevel(const QString &permission) const
|
||||
{
|
||||
if (m_room == nullptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (const auto currentPowerLevelEvent = m_room->currentState().get<Quotient::RoomPowerLevelsEvent>()) {
|
||||
if (permission == QStringLiteral("ban")) {
|
||||
return currentPowerLevelEvent->ban();
|
||||
} else if (permission == QStringLiteral("kick")) {
|
||||
return currentPowerLevelEvent->kick();
|
||||
} else if (permission == QStringLiteral("invite")) {
|
||||
return currentPowerLevelEvent->invite();
|
||||
} else if (permission == QStringLiteral("redact")) {
|
||||
return currentPowerLevelEvent->redact();
|
||||
} else if (permission == QStringLiteral("users_default")) {
|
||||
return currentPowerLevelEvent->usersDefault();
|
||||
} else if (permission == QStringLiteral("state_default")) {
|
||||
return currentPowerLevelEvent->stateDefault();
|
||||
} else if (permission == QStringLiteral("events_default")) {
|
||||
return currentPowerLevelEvent->eventsDefault();
|
||||
} else if (eventPermissions.contains(permission)) {
|
||||
return currentPowerLevelEvent->powerLevelForEvent(permission);
|
||||
} else {
|
||||
return currentPowerLevelEvent->powerLevelForState(permission);
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void PermissionsModel::setPowerLevel(const QString &permission, const int &newPowerLevel)
|
||||
{
|
||||
if (m_room == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
int clampPowerLevel = std::clamp(newPowerLevel, -1, 100);
|
||||
|
||||
const auto currentPowerLevel = powerLevel(permission);
|
||||
if (!currentPowerLevel.has_value() || currentPowerLevel == clampPowerLevel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto currentPowerLevelEvent = m_room->currentState().get<Quotient::RoomPowerLevelsEvent>()) {
|
||||
auto powerLevelContent = currentPowerLevelEvent->contentJson();
|
||||
if (powerLevelContent.contains(permission)) {
|
||||
powerLevelContent[permission] = clampPowerLevel;
|
||||
} else {
|
||||
auto eventPowerLevels = powerLevelContent[QLatin1String("events")].toObject();
|
||||
eventPowerLevels[permission] = clampPowerLevel;
|
||||
powerLevelContent[QLatin1String("events")] = eventPowerLevels;
|
||||
}
|
||||
|
||||
m_room->setState<Quotient::RoomPowerLevelsEvent>(powerLevelContent);
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_permissionsmodel.cpp"
|
||||
87
src/models/permissionsmodel.h
Normal file
87
src/models/permissionsmodel.h
Normal file
@@ -0,0 +1,87 @@
|
||||
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QQmlEngine>
|
||||
#include <optional>
|
||||
|
||||
#include "neochatroom.h"
|
||||
|
||||
/**
|
||||
* @class PermissionsModel
|
||||
*
|
||||
* This class defines the model for managing room permission levels.
|
||||
*/
|
||||
class PermissionsModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
/**
|
||||
* @brief The room to show the permissions for
|
||||
*/
|
||||
Q_PROPERTY(NeoChatRoom *room READ room WRITE setRoom NOTIFY roomChanged)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Defines the model roles.
|
||||
*/
|
||||
enum Roles {
|
||||
NameRole = Qt::DisplayRole, /**< The permission name. */
|
||||
SubtitleRole, /**< The description of the permission. */
|
||||
TypeRole, /**< The base type of the permission, normally the event type id except for ban, kick, etc. */
|
||||
LevelRole, /**< The current power level for the permission. */
|
||||
LevelNameRole, /**< The current power level for the permission as a string. */
|
||||
IsDefaultValueRole, /**< Whether the permission is a default value, e.g. for users. */
|
||||
IsBasicPermissionRole, /**< Whether the permission is one of the basic ones, e.g. kick, ban, etc. */
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
explicit PermissionsModel(QObject *parent = nullptr);
|
||||
|
||||
NeoChatRoom *room() const;
|
||||
void setRoom(NeoChatRoom *room);
|
||||
|
||||
/**
|
||||
* @brief Get the given role value at the given index.
|
||||
*
|
||||
* @sa QAbstractItemModel::data
|
||||
*/
|
||||
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
/**
|
||||
* @brief Number of rows in the model.
|
||||
*
|
||||
* @sa QAbstractItemModel::rowCount
|
||||
*/
|
||||
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
/**
|
||||
* @brief Returns a mapping from Role enum values to role names.
|
||||
*
|
||||
* @sa Roles, QAbstractItemModel::roleNames()
|
||||
*/
|
||||
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
/**
|
||||
* @brief Return the power level required for the given permission.
|
||||
*/
|
||||
std::optional<int> powerLevel(const QString &permission) const;
|
||||
|
||||
/**
|
||||
* @brief Set the power level required for the given permission.
|
||||
*/
|
||||
Q_INVOKABLE void setPowerLevel(const QString &permission, const int &newPowerLevel);
|
||||
|
||||
Q_SIGNALS:
|
||||
void roomChanged();
|
||||
|
||||
private:
|
||||
QPointer<NeoChatRoom> m_room;
|
||||
|
||||
QStringList m_permissions;
|
||||
|
||||
void initializeModel();
|
||||
};
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <Quotient/events/roompowerlevelsevent.h>
|
||||
|
||||
#include "enums/powerlevel.h"
|
||||
#include "neochatroom.h"
|
||||
|
||||
using namespace Quotient;
|
||||
@@ -94,16 +95,10 @@ QVariant UserListModel::data(const QModelIndex &index, int role) const
|
||||
|
||||
auto userPl = pl->powerLevelForUser(user->id());
|
||||
|
||||
switch (userPl) {
|
||||
case 0:
|
||||
return QStringLiteral("Member");
|
||||
case 50:
|
||||
return QStringLiteral("Moderator");
|
||||
case 100:
|
||||
return QStringLiteral("Admin");
|
||||
default:
|
||||
return QStringLiteral("Custom");
|
||||
}
|
||||
return i18nc("%1 is the name of the power level, e.g. admin and %2 is the value that represents.",
|
||||
"%1 (%2)",
|
||||
PowerLevel::nameForLevel(PowerLevel::levelForValue(userPl)),
|
||||
userPl);
|
||||
}
|
||||
|
||||
return {};
|
||||
|
||||
@@ -876,7 +876,7 @@ void NeoChatRoom::setUserPowerLevel(const QString &userID, const int &powerLevel
|
||||
qWarning() << "User is not a member of this room so power level cannot be set";
|
||||
return;
|
||||
}
|
||||
int clampPowerLevel = std::clamp(powerLevel, 0, 100);
|
||||
int clampPowerLevel = std::clamp(powerLevel, -1, 100);
|
||||
|
||||
auto powerLevelContent = currentState().get("m.room.power_levels"_ls)->contentJson();
|
||||
auto powerLevelUserOverrides = powerLevelContent["users"_ls].toObject();
|
||||
@@ -898,254 +898,6 @@ int NeoChatRoom::getUserPowerLevel(const QString &userId) const
|
||||
return powerLevelEvent->powerLevelForUser(userId);
|
||||
}
|
||||
|
||||
int NeoChatRoom::powerLevel(const QString &eventName, const bool &isStateEvent) const
|
||||
{
|
||||
const auto powerLevelEvent = currentState().get<RoomPowerLevelsEvent>();
|
||||
if (eventName == "ban"_ls) {
|
||||
return powerLevelEvent->ban();
|
||||
} else if (eventName == "kick"_ls) {
|
||||
return powerLevelEvent->kick();
|
||||
} else if (eventName == "invite"_ls) {
|
||||
return powerLevelEvent->invite();
|
||||
} else if (eventName == "redact"_ls) {
|
||||
return powerLevelEvent->redact();
|
||||
} else if (eventName == "users_default"_ls) {
|
||||
return powerLevelEvent->usersDefault();
|
||||
} else if (eventName == "state_default"_ls) {
|
||||
return powerLevelEvent->stateDefault();
|
||||
} else if (eventName == "events_default"_ls) {
|
||||
return powerLevelEvent->eventsDefault();
|
||||
} else if (isStateEvent) {
|
||||
return powerLevelEvent->powerLevelForState(eventName);
|
||||
} else {
|
||||
return powerLevelEvent->powerLevelForEvent(eventName);
|
||||
}
|
||||
}
|
||||
|
||||
void NeoChatRoom::setPowerLevel(const QString &eventName, const int &newPowerLevel, const bool &isStateEvent)
|
||||
{
|
||||
auto powerLevelContent = currentState().get("m.room.power_levels"_ls)->contentJson();
|
||||
int clampPowerLevel = std::clamp(newPowerLevel, 0, 100);
|
||||
int powerLevel = 0;
|
||||
|
||||
if (powerLevelContent.contains(eventName)) {
|
||||
powerLevel = powerLevelContent[eventName].toInt();
|
||||
|
||||
if (powerLevel != clampPowerLevel) {
|
||||
powerLevelContent[eventName] = clampPowerLevel;
|
||||
}
|
||||
} else {
|
||||
auto eventPowerLevels = powerLevelContent["events"_ls].toObject();
|
||||
|
||||
if (eventPowerLevels.contains(eventName)) {
|
||||
powerLevel = eventPowerLevels[eventName].toInt();
|
||||
} else {
|
||||
if (isStateEvent) {
|
||||
powerLevel = powerLevelContent["state_default"_ls].toInt();
|
||||
} else {
|
||||
powerLevel = powerLevelContent["events_default"_ls].toInt();
|
||||
}
|
||||
}
|
||||
|
||||
if (powerLevel != clampPowerLevel) {
|
||||
eventPowerLevels[eventName] = clampPowerLevel;
|
||||
powerLevelContent["events"_ls] = eventPowerLevels;
|
||||
}
|
||||
}
|
||||
|
||||
setState("m.room.power_levels"_ls, {}, powerLevelContent);
|
||||
}
|
||||
|
||||
int NeoChatRoom::defaultUserPowerLevel() const
|
||||
{
|
||||
return powerLevel("users_default"_ls);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setDefaultUserPowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("users_default"_ls, newPowerLevel);
|
||||
}
|
||||
|
||||
int NeoChatRoom::invitePowerLevel() const
|
||||
{
|
||||
return powerLevel("invite"_ls);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setInvitePowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("invite"_ls, newPowerLevel);
|
||||
}
|
||||
|
||||
int NeoChatRoom::kickPowerLevel() const
|
||||
{
|
||||
return powerLevel("kick"_ls);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setKickPowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("kick"_ls, newPowerLevel);
|
||||
}
|
||||
|
||||
int NeoChatRoom::banPowerLevel() const
|
||||
{
|
||||
return powerLevel("ban"_ls);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setBanPowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("ban"_ls, newPowerLevel);
|
||||
}
|
||||
|
||||
int NeoChatRoom::redactPowerLevel() const
|
||||
{
|
||||
return powerLevel("redact"_ls);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setRedactPowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("redact"_ls, newPowerLevel);
|
||||
}
|
||||
|
||||
int NeoChatRoom::statePowerLevel() const
|
||||
{
|
||||
return powerLevel("state_default"_ls);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setStatePowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("state_default"_ls, newPowerLevel);
|
||||
}
|
||||
|
||||
int NeoChatRoom::defaultEventPowerLevel() const
|
||||
{
|
||||
return powerLevel("events_default"_ls);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setDefaultEventPowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("events_default"_ls, newPowerLevel);
|
||||
}
|
||||
|
||||
int NeoChatRoom::powerLevelPowerLevel() const
|
||||
{
|
||||
return powerLevel("m.room.power_levels"_ls, true);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setPowerLevelPowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("m.room.power_levels"_ls, newPowerLevel, true);
|
||||
}
|
||||
|
||||
int NeoChatRoom::namePowerLevel() const
|
||||
{
|
||||
return powerLevel("m.room.name"_ls, true);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setNamePowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("m.room.name"_ls, newPowerLevel, true);
|
||||
}
|
||||
|
||||
int NeoChatRoom::avatarPowerLevel() const
|
||||
{
|
||||
return powerLevel("m.room.avatar"_ls, true);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setAvatarPowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("m.room.avatar"_ls, newPowerLevel, true);
|
||||
}
|
||||
|
||||
int NeoChatRoom::canonicalAliasPowerLevel() const
|
||||
{
|
||||
return powerLevel("m.room.canonical_alias"_ls, true);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setCanonicalAliasPowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("m.room.canonical_alias"_ls, newPowerLevel, true);
|
||||
}
|
||||
|
||||
int NeoChatRoom::topicPowerLevel() const
|
||||
{
|
||||
return powerLevel("m.room.topic"_ls, true);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setTopicPowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("m.room.topic"_ls, newPowerLevel, true);
|
||||
}
|
||||
|
||||
int NeoChatRoom::encryptionPowerLevel() const
|
||||
{
|
||||
return powerLevel("m.room.encryption"_ls, true);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setEncryptionPowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("m.room.encryption"_ls, newPowerLevel, true);
|
||||
}
|
||||
|
||||
int NeoChatRoom::historyVisibilityPowerLevel() const
|
||||
{
|
||||
return powerLevel("m.room.history_visibility"_ls, true);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setHistoryVisibilityPowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("m.room.history_visibility"_ls, newPowerLevel, true);
|
||||
}
|
||||
|
||||
int NeoChatRoom::pinnedEventsPowerLevel() const
|
||||
{
|
||||
return powerLevel("m.room.pinned_events"_ls, true);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setPinnedEventsPowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("m.room.pinned_events"_ls, newPowerLevel, true);
|
||||
}
|
||||
|
||||
int NeoChatRoom::tombstonePowerLevel() const
|
||||
{
|
||||
return powerLevel("m.room.tombstone"_ls, true);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setTombstonePowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("m.room.tombstone"_ls, newPowerLevel, true);
|
||||
}
|
||||
|
||||
int NeoChatRoom::serverAclPowerLevel() const
|
||||
{
|
||||
return powerLevel("m.room.server_acl"_ls, true);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setServerAclPowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("m.room.server_acl"_ls, newPowerLevel, true);
|
||||
}
|
||||
|
||||
int NeoChatRoom::spaceChildPowerLevel() const
|
||||
{
|
||||
return powerLevel("m.space.child"_ls, true);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setSpaceChildPowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("m.space.child"_ls, newPowerLevel, true);
|
||||
}
|
||||
|
||||
int NeoChatRoom::spaceParentPowerLevel() const
|
||||
{
|
||||
return powerLevel("m.space.parent"_ls, true);
|
||||
}
|
||||
|
||||
void NeoChatRoom::setSpaceParentPowerLevel(const int &newPowerLevel)
|
||||
{
|
||||
setPowerLevel("m.space.parent"_ls, newPowerLevel, true);
|
||||
}
|
||||
|
||||
QCoro::Task<void> NeoChatRoom::doDeleteMessagesByUser(const QString &user, QString reason)
|
||||
{
|
||||
QStringList events;
|
||||
|
||||
@@ -212,101 +212,6 @@ class NeoChatRoom : public Quotient::Room
|
||||
*/
|
||||
Q_PROPERTY(bool canEncryptRoom READ canEncryptRoom NOTIFY canEncryptRoomChanged)
|
||||
|
||||
/**
|
||||
* @brief The default power level in the room for new users.
|
||||
*/
|
||||
Q_PROPERTY(int defaultUserPowerLevel READ defaultUserPowerLevel WRITE setDefaultUserPowerLevel NOTIFY defaultUserPowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The power level required to invite users to the room.
|
||||
*/
|
||||
Q_PROPERTY(int invitePowerLevel READ invitePowerLevel WRITE setInvitePowerLevel NOTIFY invitePowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The power level required to kick users from the room.
|
||||
*/
|
||||
Q_PROPERTY(int kickPowerLevel READ kickPowerLevel WRITE setKickPowerLevel NOTIFY kickPowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The power level required to ban users from the room.
|
||||
*/
|
||||
Q_PROPERTY(int banPowerLevel READ banPowerLevel WRITE setBanPowerLevel NOTIFY banPowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The power level required to delete other user messages.
|
||||
*/
|
||||
Q_PROPERTY(int redactPowerLevel READ redactPowerLevel WRITE setRedactPowerLevel NOTIFY redactPowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The default power level for state events that are not explicitly specified.
|
||||
*/
|
||||
Q_PROPERTY(int statePowerLevel READ statePowerLevel WRITE setStatePowerLevel NOTIFY statePowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The default power level for event that are not explicitly specified.
|
||||
*/
|
||||
Q_PROPERTY(int defaultEventPowerLevel READ defaultEventPowerLevel WRITE setDefaultEventPowerLevel NOTIFY defaultEventPowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The power level required to change power levels for the room.
|
||||
*/
|
||||
Q_PROPERTY(int powerLevelPowerLevel READ powerLevelPowerLevel WRITE setPowerLevelPowerLevel NOTIFY powerLevelPowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The power level required to change the room name.
|
||||
*/
|
||||
Q_PROPERTY(int namePowerLevel READ namePowerLevel WRITE setNamePowerLevel NOTIFY namePowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The power level required to change the room avatar.
|
||||
*/
|
||||
Q_PROPERTY(int avatarPowerLevel READ avatarPowerLevel WRITE setAvatarPowerLevel NOTIFY avatarPowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The power level required to change the room aliases.
|
||||
*/
|
||||
Q_PROPERTY(int canonicalAliasPowerLevel READ canonicalAliasPowerLevel WRITE setCanonicalAliasPowerLevel NOTIFY canonicalAliasPowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The power level required to change the room topic.
|
||||
*/
|
||||
Q_PROPERTY(int topicPowerLevel READ topicPowerLevel WRITE setTopicPowerLevel NOTIFY topicPowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The power level required to encrypt the room.
|
||||
*/
|
||||
Q_PROPERTY(int encryptionPowerLevel READ encryptionPowerLevel WRITE setEncryptionPowerLevel NOTIFY encryptionPowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The power level required to change the room history visibility.
|
||||
*/
|
||||
Q_PROPERTY(int historyVisibilityPowerLevel READ historyVisibilityPowerLevel WRITE setHistoryVisibilityPowerLevel NOTIFY historyVisibilityPowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The power level required to pin events in the room.
|
||||
*/
|
||||
Q_PROPERTY(int pinnedEventsPowerLevel READ pinnedEventsPowerLevel WRITE setPinnedEventsPowerLevel NOTIFY pinnedEventsPowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The power level required to upgrade the room.
|
||||
*/
|
||||
Q_PROPERTY(int tombstonePowerLevel READ tombstonePowerLevel WRITE setTombstonePowerLevel NOTIFY tombstonePowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The power level required to set the room server access control list (ACL).
|
||||
*/
|
||||
Q_PROPERTY(int serverAclPowerLevel READ serverAclPowerLevel WRITE setServerAclPowerLevel NOTIFY serverAclPowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The power level required to add children to a space.
|
||||
*/
|
||||
Q_PROPERTY(int spaceChildPowerLevel READ spaceChildPowerLevel WRITE setSpaceChildPowerLevel NOTIFY spaceChildPowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The power level required to set the room parent space.
|
||||
*/
|
||||
Q_PROPERTY(int spaceParentPowerLevel READ spaceParentPowerLevel WRITE setSpaceParentPowerLevel NOTIFY spaceParentPowerLevelChanged)
|
||||
|
||||
/**
|
||||
* @brief The cache for the main chat bar in the room.
|
||||
*/
|
||||
@@ -683,66 +588,6 @@ public:
|
||||
|
||||
Q_INVOKABLE void setUserPowerLevel(const QString &userID, const int &powerLevel);
|
||||
|
||||
[[nodiscard]] int powerLevel(const QString &eventName, const bool &isStateEvent = false) const;
|
||||
void setPowerLevel(const QString &eventName, const int &newPowerLevel, const bool &isStateEvent = false);
|
||||
|
||||
[[nodiscard]] int defaultUserPowerLevel() const;
|
||||
void setDefaultUserPowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int invitePowerLevel() const;
|
||||
void setInvitePowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int kickPowerLevel() const;
|
||||
void setKickPowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int banPowerLevel() const;
|
||||
void setBanPowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int redactPowerLevel() const;
|
||||
void setRedactPowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int statePowerLevel() const;
|
||||
void setStatePowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int defaultEventPowerLevel() const;
|
||||
void setDefaultEventPowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int powerLevelPowerLevel() const;
|
||||
void setPowerLevelPowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int namePowerLevel() const;
|
||||
void setNamePowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int avatarPowerLevel() const;
|
||||
void setAvatarPowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int canonicalAliasPowerLevel() const;
|
||||
void setCanonicalAliasPowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int topicPowerLevel() const;
|
||||
void setTopicPowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int encryptionPowerLevel() const;
|
||||
void setEncryptionPowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int historyVisibilityPowerLevel() const;
|
||||
void setHistoryVisibilityPowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int pinnedEventsPowerLevel() const;
|
||||
void setPinnedEventsPowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int tombstonePowerLevel() const;
|
||||
void setTombstonePowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int serverAclPowerLevel() const;
|
||||
void setServerAclPowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int spaceChildPowerLevel() const;
|
||||
void setSpaceChildPowerLevel(const int &newPowerLevel);
|
||||
|
||||
[[nodiscard]] int spaceParentPowerLevel() const;
|
||||
void setSpaceParentPowerLevel(const int &newPowerLevel);
|
||||
|
||||
ChatBarCache *mainCache() const;
|
||||
|
||||
ChatBarCache *editCache() const;
|
||||
@@ -858,25 +703,6 @@ Q_SIGNALS:
|
||||
void defaultUrlPreviewStateChanged();
|
||||
void urlPreviewEnabledChanged();
|
||||
void maxRoomVersionChanged();
|
||||
void defaultUserPowerLevelChanged();
|
||||
void invitePowerLevelChanged();
|
||||
void kickPowerLevelChanged();
|
||||
void banPowerLevelChanged();
|
||||
void redactPowerLevelChanged();
|
||||
void statePowerLevelChanged();
|
||||
void defaultEventPowerLevelChanged();
|
||||
void powerLevelPowerLevelChanged();
|
||||
void namePowerLevelChanged();
|
||||
void avatarPowerLevelChanged();
|
||||
void canonicalAliasPowerLevelChanged();
|
||||
void topicPowerLevelChanged();
|
||||
void encryptionPowerLevelChanged();
|
||||
void historyVisibilityPowerLevelChanged();
|
||||
void pinnedEventsPowerLevelChanged();
|
||||
void tombstonePowerLevelChanged();
|
||||
void serverAclPowerLevelChanged();
|
||||
void spaceChildPowerLevelChanged();
|
||||
void spaceParentPowerLevelChanged();
|
||||
void replyLoaded(const QString &eventId, const QString &replyId);
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
@@ -28,32 +28,14 @@ Kirigami.Dialog {
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormCard {
|
||||
ColumnLayout {
|
||||
FormCard.FormComboBoxDelegate {
|
||||
id: powerLevelComboBox
|
||||
|
||||
text: i18n("New power level")
|
||||
model: ListModel {
|
||||
id: powerLevelModel
|
||||
}
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
|
||||
// Done this way so we can have translated strings.
|
||||
Component.onCompleted: {
|
||||
powerLevelModel.append({
|
||||
"text": i18n("Member (0)"),
|
||||
"powerLevel": 0
|
||||
});
|
||||
powerLevelModel.append({
|
||||
"text": i18n("Moderator (50)"),
|
||||
"powerLevel": 50
|
||||
});
|
||||
powerLevelModel.append({
|
||||
"text": i18n("Admin (100)"),
|
||||
"powerLevel": 100
|
||||
});
|
||||
}
|
||||
model: PowerLevelModel {}
|
||||
textRole: "name"
|
||||
valueRole: "value"
|
||||
}
|
||||
}
|
||||
customFooterActions: [
|
||||
|
||||
@@ -25,8 +25,12 @@ FormCard.FormCardPage {
|
||||
room: root.room
|
||||
}
|
||||
|
||||
property ListModel powerLevelModel: ListModel {
|
||||
id: powerLevelModel
|
||||
readonly property PowerLevelModel powerLevelModel: PowerLevelModel {
|
||||
showMute: false
|
||||
}
|
||||
|
||||
readonly property PermissionsModel permissionsModel: PermissionsModel {
|
||||
room: root.room
|
||||
}
|
||||
|
||||
FormCard.FormHeader {
|
||||
@@ -40,10 +44,16 @@ FormCard.FormCardPage {
|
||||
sortOrder: Qt.DescendingOrder
|
||||
filterRowCallback: function (source_row, source_parent) {
|
||||
let powerLevelRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), UserListModel.PowerLevelRole);
|
||||
return powerLevelRole > 0;
|
||||
return powerLevelRole != 0;
|
||||
}
|
||||
}
|
||||
delegate: FormCard.FormTextDelegate {
|
||||
id: privilegedUserDelegate
|
||||
required property string userId
|
||||
required property string name
|
||||
required property int powerLevel
|
||||
required property string powerLevelString
|
||||
|
||||
text: name
|
||||
textItem.textFormat: Text.PlainText
|
||||
description: userId
|
||||
@@ -51,37 +61,23 @@ FormCard.FormCardPage {
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
QQC2.Label {
|
||||
id: powerLevelLabel
|
||||
visible: !room.canSendState("m.room.power_levels") || (room.getUserPowerLevel(room.localUser.id) <= model.powerLevel && model.userId != room.localUser.id)
|
||||
text: powerLevelString
|
||||
visible: !room.canSendState("m.room.power_levels") || (room.getUserPowerLevel(room.localUser.id) <= privilegedUserDelegate.powerLevel && privilegedUserDelegate.userId != room.localUser.id)
|
||||
text: privilegedUserDelegate.powerLevelString
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
}
|
||||
QQC2.ComboBox {
|
||||
focusPolicy: Qt.NoFocus // provided by parent
|
||||
model: powerLevelModel
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: PowerLevelModel {}
|
||||
textRole: "name"
|
||||
valueRole: "value"
|
||||
visible: !powerLevelLabel.visible
|
||||
Component.onCompleted: {
|
||||
/**
|
||||
* This is very silly but the only way to populate the model with
|
||||
* translated strings. Done here because the model needs to be filled
|
||||
* before the first delegate sets it's current index.
|
||||
*/
|
||||
if (powerLevelModel.count == 0) {
|
||||
powerLevelModel.append({
|
||||
"text": i18n("Member (0)"),
|
||||
"powerLevel": 0
|
||||
});
|
||||
powerLevelModel.append({
|
||||
"text": i18n("Moderator (50)"),
|
||||
"powerLevel": 50
|
||||
});
|
||||
powerLevelModel.append({
|
||||
"text": i18n("Admin (100)"),
|
||||
"powerLevel": 100
|
||||
});
|
||||
let index = indexOfValue(privilegedUserDelegate.powerLevel)
|
||||
if (index === -1) {
|
||||
displayText = privilegedUserDelegate.powerLevelString;
|
||||
} else {
|
||||
currentIndex = index;
|
||||
}
|
||||
currentIndex = indexOfValue(powerLevel);
|
||||
}
|
||||
onActivated: {
|
||||
room.setUserPowerLevel(userId, currentValue);
|
||||
@@ -243,37 +239,36 @@ FormCard.FormCardPage {
|
||||
}
|
||||
FormCard.FormCard {
|
||||
visible: room.canSendState("m.room.power_levels")
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Default user power level")
|
||||
description: i18n("This is power level for all new users when joining the room")
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.defaultUserPowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.defaultUserPowerLevel = currentValue;
|
||||
Repeater {
|
||||
model: KSortFilterProxyModel {
|
||||
sourceModel: root.permissionsModel
|
||||
filterRowCallback: function (source_row, source_parent) {
|
||||
return sourceModel.data(sourceModel.index(source_row, 0, source_parent), PermissionsModel.IsDefaultValueRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Default power level to set the room state")
|
||||
description: i18n("This is used for all state events that do not have their own entry here")
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.statePowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.statePowerLevel = currentValue;
|
||||
}
|
||||
}
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Default power level to send messages")
|
||||
description: i18n("This is used for all message events that do not have their own entry here")
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.defaultEventPowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.defaultEventPowerLevel = currentValue;
|
||||
delegate: FormCard.FormComboBoxDelegate {
|
||||
required property string name
|
||||
required property string subtitle
|
||||
required property string type
|
||||
required property int level
|
||||
required property string levelName
|
||||
|
||||
text: name
|
||||
description: subtitle
|
||||
textRole: "name"
|
||||
valueRole: "value"
|
||||
model: root.powerLevelModel
|
||||
Component.onCompleted: {
|
||||
let index = indexOfValue(level)
|
||||
if (index === -1) {
|
||||
displayText = levelName;
|
||||
} else {
|
||||
currentIndex = index;
|
||||
}
|
||||
}
|
||||
onCurrentValueChanged: if (root.room.canSendState("m.room.power_levels")) {
|
||||
root.permissionsModel.setPowerLevel(type, currentValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -284,44 +279,36 @@ FormCard.FormCardPage {
|
||||
}
|
||||
FormCard.FormCard {
|
||||
visible: room.canSendState("m.room.power_levels")
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Invite users")
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.invitePowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.invitePowerLevel = currentValue;
|
||||
Repeater {
|
||||
model: KSortFilterProxyModel {
|
||||
sourceModel: root.permissionsModel
|
||||
filterRowCallback: function (source_row, source_parent) {
|
||||
return sourceModel.data(sourceModel.index(source_row, 0, source_parent), PermissionsModel.IsBasicPermissionRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Kick users")
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.kickPowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.kickPowerLevel = currentValue;
|
||||
}
|
||||
}
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Ban users")
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.banPowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.banPowerLevel = currentValue;
|
||||
}
|
||||
}
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Remove message sent by other users")
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.redactPowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.redactPowerLevel = currentValue;
|
||||
delegate: FormCard.FormComboBoxDelegate {
|
||||
required property string name
|
||||
required property string subtitle
|
||||
required property string type
|
||||
required property int level
|
||||
required property string levelName
|
||||
|
||||
text: name
|
||||
description: subtitle
|
||||
textRole: "name"
|
||||
valueRole: "value"
|
||||
model: root.powerLevelModel
|
||||
Component.onCompleted: {
|
||||
let index = indexOfValue(level)
|
||||
if (index === -1) {
|
||||
displayText = levelName;
|
||||
} else {
|
||||
currentIndex = index;
|
||||
}
|
||||
}
|
||||
onCurrentValueChanged: if (root.room.canSendState("m.room.power_levels")) {
|
||||
root.permissionsModel.setPowerLevel(type, currentValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -332,137 +319,91 @@ FormCard.FormCardPage {
|
||||
}
|
||||
FormCard.FormCard {
|
||||
visible: room.canSendState("m.room.power_levels")
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Change user permissions")
|
||||
description: "m.room.power_levels"
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.powerLevelPowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.powerLevelPowerLevel = currentValue;
|
||||
Repeater {
|
||||
model: KSortFilterProxyModel {
|
||||
sourceModel: root.permissionsModel
|
||||
filterRowCallback: function (source_row, source_parent) {
|
||||
let isBasicPermissionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PermissionsModel.IsBasicPermissionRole);
|
||||
let isDefaultValueRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PermissionsModel.IsDefaultValueRole);
|
||||
return !isBasicPermissionRole && !isDefaultValueRole;
|
||||
}
|
||||
}
|
||||
delegate: FormCard.FormComboBoxDelegate {
|
||||
required property string name
|
||||
required property string subtitle
|
||||
required property string type
|
||||
required property int level
|
||||
required property string levelName
|
||||
|
||||
text: name
|
||||
description: subtitle
|
||||
textRole: "name"
|
||||
valueRole: "value"
|
||||
model: root.powerLevelModel
|
||||
Component.onCompleted: {
|
||||
let index = indexOfValue(level)
|
||||
if (index === -1) {
|
||||
displayText = levelName;
|
||||
} else {
|
||||
currentIndex = index;
|
||||
}
|
||||
}
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
root.permissionsModel.setPowerLevel(type, currentValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Change the room name")
|
||||
description: "m.room.name"
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.namePowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.namePowerLevel = currentValue;
|
||||
}
|
||||
}
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Change the room avatar")
|
||||
description: "m.room.avatar"
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.avatarPowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.avatarPowerLevel = currentValue;
|
||||
}
|
||||
}
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Change the room canonical alias")
|
||||
description: "m.room.canonical_alias"
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.canonicalAliasPowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.canonicalAliasPowerLevel = currentValue;
|
||||
}
|
||||
}
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Change the room topic")
|
||||
description: "m.room.topic"
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.topicPowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.topicPowerLevel = currentValue;
|
||||
}
|
||||
}
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Enable encryption for the room")
|
||||
description: "m.room.encryption"
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.encryptionPowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.encryptionPowerLevel = currentValue;
|
||||
}
|
||||
}
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Change the room history visibility")
|
||||
description: "m.room.history_visibility"
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.historyVisibilityPowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.historyVisibilityPowerLevel = currentValue;
|
||||
}
|
||||
}
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Set pinned events")
|
||||
description: "m.room.pinned_events"
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.pinnedEventsPowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.pinnedEventsPowerLevel = currentValue;
|
||||
}
|
||||
}
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Upgrade the room")
|
||||
description: "m.room.tombstone"
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.tombstonePowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.tombstonePowerLevel = currentValue;
|
||||
}
|
||||
}
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Set the room server access control list (ACL)")
|
||||
description: "m.room.server_acl"
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.serverAclPowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.serverAclPowerLevel = currentValue;
|
||||
}
|
||||
}
|
||||
FormCard.FormComboBoxDelegate {
|
||||
visible: room.isSpace
|
||||
text: i18n("Set the children of this space")
|
||||
description: "m.space.child"
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.spaceChildPowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.spaceChildPowerLevel = currentValue;
|
||||
}
|
||||
}
|
||||
FormCard.FormComboBoxDelegate {
|
||||
text: i18n("Set the parent space of this room")
|
||||
description: "m.space.parent"
|
||||
textRole: "text"
|
||||
valueRole: "powerLevel"
|
||||
model: powerLevelModel
|
||||
Component.onCompleted: currentIndex = indexOfValue(room.spaceChildPowerLevel)
|
||||
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
|
||||
room.spaceParentPowerLevel = currentValue;
|
||||
FormCard.AbstractFormDelegate {
|
||||
Layout.fillWidth: true
|
||||
|
||||
contentItem: RowLayout {
|
||||
Kirigami.ActionTextField {
|
||||
id: newEventAddField
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
placeholderText: i18n("Event Type…")
|
||||
enabled: NotificationsManager.keywordNotificationAction !== PushRuleAction.Unknown
|
||||
|
||||
rightActions: Kirigami.Action {
|
||||
icon.name: "edit-clear"
|
||||
visible: newEventAddField.text.length > 0
|
||||
onTriggered: {
|
||||
newEventAddField.text = "";
|
||||
}
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
root.permissionsModel.setPowerLevel(newEventAddField.text, newEventPowerLevel.currentValue);
|
||||
newEventAddField.text = "";
|
||||
}
|
||||
}
|
||||
QQC2.ComboBox {
|
||||
id: newEventPowerLevel
|
||||
focusPolicy: Qt.NoFocus // provided by parent
|
||||
model: root.powerLevelModel
|
||||
textRole: "name"
|
||||
valueRole: "value"
|
||||
}
|
||||
QQC2.Button {
|
||||
id: addButton
|
||||
|
||||
text: i18n("Add keyword")
|
||||
Accessible.name: text
|
||||
icon.name: "list-add"
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
enabled: newEventAddField.text.length > 0
|
||||
|
||||
onClicked: {
|
||||
root.permissionsModel.setPowerLevel(newEventAddField.text, newEventPowerLevel.currentValue);
|
||||
newEventAddField.text = "";
|
||||
}
|
||||
|
||||
QQC2.ToolTip {
|
||||
text: addButton.text
|
||||
delay: Kirigami.Units.toolTipDelay
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user