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:
James Graham
2024-05-25 16:25:39 +00:00
parent 8199653ddd
commit a48151920d
10 changed files with 736 additions and 678 deletions

View File

@@ -181,6 +181,10 @@ add_library(neochat STATIC
jobs/neochatadd3pidjob.h jobs/neochatadd3pidjob.h
identityserverhelper.cpp identityserverhelper.cpp
identityserverhelper.h identityserverhelper.h
enums/powerlevel.cpp
enums/powerlevel.h
models/permissionsmodel.cpp
models/permissionsmodel.h
) )
set_source_files_properties(qml/OsmLocationPlugin.qml PROPERTIES set_source_files_properties(qml/OsmLocationPlugin.qml PROPERTIES

107
src/enums/powerlevel.cpp Normal file
View 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
View 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;
};

View 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"

View 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();
};

View File

@@ -7,6 +7,7 @@
#include <Quotient/events/roompowerlevelsevent.h> #include <Quotient/events/roompowerlevelsevent.h>
#include "enums/powerlevel.h"
#include "neochatroom.h" #include "neochatroom.h"
using namespace Quotient; using namespace Quotient;
@@ -94,16 +95,10 @@ QVariant UserListModel::data(const QModelIndex &index, int role) const
auto userPl = pl->powerLevelForUser(user->id()); auto userPl = pl->powerLevelForUser(user->id());
switch (userPl) { return i18nc("%1 is the name of the power level, e.g. admin and %2 is the value that represents.",
case 0: "%1 (%2)",
return QStringLiteral("Member"); PowerLevel::nameForLevel(PowerLevel::levelForValue(userPl)),
case 50: userPl);
return QStringLiteral("Moderator");
case 100:
return QStringLiteral("Admin");
default:
return QStringLiteral("Custom");
}
} }
return {}; return {};

View File

@@ -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"; qWarning() << "User is not a member of this room so power level cannot be set";
return; 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 powerLevelContent = currentState().get("m.room.power_levels"_ls)->contentJson();
auto powerLevelUserOverrides = powerLevelContent["users"_ls].toObject(); auto powerLevelUserOverrides = powerLevelContent["users"_ls].toObject();
@@ -898,254 +898,6 @@ int NeoChatRoom::getUserPowerLevel(const QString &userId) const
return powerLevelEvent->powerLevelForUser(userId); 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) QCoro::Task<void> NeoChatRoom::doDeleteMessagesByUser(const QString &user, QString reason)
{ {
QStringList events; QStringList events;

View File

@@ -212,101 +212,6 @@ class NeoChatRoom : public Quotient::Room
*/ */
Q_PROPERTY(bool canEncryptRoom READ canEncryptRoom NOTIFY canEncryptRoomChanged) 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. * @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); 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 *mainCache() const;
ChatBarCache *editCache() const; ChatBarCache *editCache() const;
@@ -858,25 +703,6 @@ Q_SIGNALS:
void defaultUrlPreviewStateChanged(); void defaultUrlPreviewStateChanged();
void urlPreviewEnabledChanged(); void urlPreviewEnabledChanged();
void maxRoomVersionChanged(); 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); void replyLoaded(const QString &eventId, const QString &replyId);
public Q_SLOTS: public Q_SLOTS:

View File

@@ -28,32 +28,14 @@ Kirigami.Dialog {
} }
} }
FormCard.FormCard { ColumnLayout {
FormCard.FormComboBoxDelegate { FormCard.FormComboBoxDelegate {
id: powerLevelComboBox id: powerLevelComboBox
text: i18n("New power level") text: i18n("New power level")
model: ListModel { model: PowerLevelModel {}
id: powerLevelModel textRole: "name"
} valueRole: "value"
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
});
}
} }
} }
customFooterActions: [ customFooterActions: [

View File

@@ -25,8 +25,12 @@ FormCard.FormCardPage {
room: root.room room: root.room
} }
property ListModel powerLevelModel: ListModel { readonly property PowerLevelModel powerLevelModel: PowerLevelModel {
id: powerLevelModel showMute: false
}
readonly property PermissionsModel permissionsModel: PermissionsModel {
room: root.room
} }
FormCard.FormHeader { FormCard.FormHeader {
@@ -40,10 +44,16 @@ FormCard.FormCardPage {
sortOrder: Qt.DescendingOrder sortOrder: Qt.DescendingOrder
filterRowCallback: function (source_row, source_parent) { filterRowCallback: function (source_row, source_parent) {
let powerLevelRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), UserListModel.PowerLevelRole); let powerLevelRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), UserListModel.PowerLevelRole);
return powerLevelRole > 0; return powerLevelRole != 0;
} }
} }
delegate: FormCard.FormTextDelegate { delegate: FormCard.FormTextDelegate {
id: privilegedUserDelegate
required property string userId
required property string name
required property int powerLevel
required property string powerLevelString
text: name text: name
textItem.textFormat: Text.PlainText textItem.textFormat: Text.PlainText
description: userId description: userId
@@ -51,37 +61,23 @@ FormCard.FormCardPage {
spacing: Kirigami.Units.largeSpacing spacing: Kirigami.Units.largeSpacing
QQC2.Label { QQC2.Label {
id: powerLevelLabel id: powerLevelLabel
visible: !room.canSendState("m.room.power_levels") || (room.getUserPowerLevel(room.localUser.id) <= model.powerLevel && model.userId != room.localUser.id) visible: !room.canSendState("m.room.power_levels") || (room.getUserPowerLevel(room.localUser.id) <= privilegedUserDelegate.powerLevel && privilegedUserDelegate.userId != room.localUser.id)
text: powerLevelString text: privilegedUserDelegate.powerLevelString
color: Kirigami.Theme.disabledTextColor color: Kirigami.Theme.disabledTextColor
} }
QQC2.ComboBox { QQC2.ComboBox {
focusPolicy: Qt.NoFocus // provided by parent focusPolicy: Qt.NoFocus // provided by parent
model: powerLevelModel model: PowerLevelModel {}
textRole: "text" textRole: "name"
valueRole: "powerLevel" valueRole: "value"
visible: !powerLevelLabel.visible visible: !powerLevelLabel.visible
Component.onCompleted: { Component.onCompleted: {
/** let index = indexOfValue(privilegedUserDelegate.powerLevel)
* This is very silly but the only way to populate the model with if (index === -1) {
* translated strings. Done here because the model needs to be filled displayText = privilegedUserDelegate.powerLevelString;
* before the first delegate sets it's current index. } else {
*/ currentIndex = 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
});
} }
currentIndex = indexOfValue(powerLevel);
} }
onActivated: { onActivated: {
room.setUserPowerLevel(userId, currentValue); room.setUserPowerLevel(userId, currentValue);
@@ -243,37 +239,36 @@ FormCard.FormCardPage {
} }
FormCard.FormCard { FormCard.FormCard {
visible: room.canSendState("m.room.power_levels") visible: room.canSendState("m.room.power_levels")
FormCard.FormComboBoxDelegate { Repeater {
text: i18n("Default user power level") model: KSortFilterProxyModel {
description: i18n("This is power level for all new users when joining the room") sourceModel: root.permissionsModel
textRole: "text" filterRowCallback: function (source_row, source_parent) {
valueRole: "powerLevel" return sourceModel.data(sourceModel.index(source_row, 0, source_parent), PermissionsModel.IsDefaultValueRole);
model: powerLevelModel }
Component.onCompleted: currentIndex = indexOfValue(room.defaultUserPowerLevel)
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
room.defaultUserPowerLevel = currentValue;
} }
} delegate: FormCard.FormComboBoxDelegate {
FormCard.FormComboBoxDelegate { required property string name
text: i18n("Default power level to set the room state") required property string subtitle
description: i18n("This is used for all state events that do not have their own entry here") required property string type
textRole: "text" required property int level
valueRole: "powerLevel" required property string levelName
model: powerLevelModel
Component.onCompleted: currentIndex = indexOfValue(room.statePowerLevel) text: name
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { description: subtitle
room.statePowerLevel = currentValue; textRole: "name"
} valueRole: "value"
} model: root.powerLevelModel
FormCard.FormComboBoxDelegate { Component.onCompleted: {
text: i18n("Default power level to send messages") let index = indexOfValue(level)
description: i18n("This is used for all message events that do not have their own entry here") if (index === -1) {
textRole: "text" displayText = levelName;
valueRole: "powerLevel" } else {
model: powerLevelModel currentIndex = index;
Component.onCompleted: currentIndex = indexOfValue(room.defaultEventPowerLevel) }
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { }
room.defaultEventPowerLevel = currentValue; onCurrentValueChanged: if (root.room.canSendState("m.room.power_levels")) {
root.permissionsModel.setPowerLevel(type, currentValue);
}
} }
} }
} }
@@ -284,44 +279,36 @@ FormCard.FormCardPage {
} }
FormCard.FormCard { FormCard.FormCard {
visible: room.canSendState("m.room.power_levels") visible: room.canSendState("m.room.power_levels")
FormCard.FormComboBoxDelegate { Repeater {
text: i18n("Invite users") model: KSortFilterProxyModel {
textRole: "text" sourceModel: root.permissionsModel
valueRole: "powerLevel" filterRowCallback: function (source_row, source_parent) {
model: powerLevelModel return sourceModel.data(sourceModel.index(source_row, 0, source_parent), PermissionsModel.IsBasicPermissionRole);
Component.onCompleted: currentIndex = indexOfValue(room.invitePowerLevel) }
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
room.invitePowerLevel = currentValue;
} }
} delegate: FormCard.FormComboBoxDelegate {
FormCard.FormComboBoxDelegate { required property string name
text: i18n("Kick users") required property string subtitle
textRole: "text" required property string type
valueRole: "powerLevel" required property int level
model: powerLevelModel required property string levelName
Component.onCompleted: currentIndex = indexOfValue(room.kickPowerLevel)
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { text: name
room.kickPowerLevel = currentValue; description: subtitle
} textRole: "name"
} valueRole: "value"
FormCard.FormComboBoxDelegate { model: root.powerLevelModel
text: i18n("Ban users") Component.onCompleted: {
textRole: "text" let index = indexOfValue(level)
valueRole: "powerLevel" if (index === -1) {
model: powerLevelModel displayText = levelName;
Component.onCompleted: currentIndex = indexOfValue(room.banPowerLevel) } else {
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { currentIndex = index;
room.banPowerLevel = currentValue; }
} }
} onCurrentValueChanged: if (root.room.canSendState("m.room.power_levels")) {
FormCard.FormComboBoxDelegate { root.permissionsModel.setPowerLevel(type, currentValue);
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;
} }
} }
} }
@@ -332,137 +319,91 @@ FormCard.FormCardPage {
} }
FormCard.FormCard { FormCard.FormCard {
visible: room.canSendState("m.room.power_levels") visible: room.canSendState("m.room.power_levels")
FormCard.FormComboBoxDelegate { Repeater {
text: i18n("Change user permissions") model: KSortFilterProxyModel {
description: "m.room.power_levels" sourceModel: root.permissionsModel
textRole: "text" filterRowCallback: function (source_row, source_parent) {
valueRole: "powerLevel" let isBasicPermissionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PermissionsModel.IsBasicPermissionRole);
model: powerLevelModel let isDefaultValueRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PermissionsModel.IsDefaultValueRole);
Component.onCompleted: currentIndex = indexOfValue(room.powerLevelPowerLevel) return !isBasicPermissionRole && !isDefaultValueRole;
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { }
room.powerLevelPowerLevel = 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 (room.canSendState("m.room.power_levels")) {
root.permissionsModel.setPowerLevel(type, currentValue);
}
} }
} }
FormCard.FormComboBoxDelegate { FormCard.AbstractFormDelegate {
text: i18n("Change the room name") Layout.fillWidth: true
description: "m.room.name"
textRole: "text" contentItem: RowLayout {
valueRole: "powerLevel" Kirigami.ActionTextField {
model: powerLevelModel id: newEventAddField
Component.onCompleted: currentIndex = indexOfValue(room.namePowerLevel)
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { Layout.fillWidth: true
room.namePowerLevel = currentValue;
} placeholderText: i18n("Event Type…")
} enabled: NotificationsManager.keywordNotificationAction !== PushRuleAction.Unknown
FormCard.FormComboBoxDelegate {
text: i18n("Change the room avatar") rightActions: Kirigami.Action {
description: "m.room.avatar" icon.name: "edit-clear"
textRole: "text" visible: newEventAddField.text.length > 0
valueRole: "powerLevel" onTriggered: {
model: powerLevelModel newEventAddField.text = "";
Component.onCompleted: currentIndex = indexOfValue(room.avatarPowerLevel) }
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { }
room.avatarPowerLevel = currentValue;
} onAccepted: {
} root.permissionsModel.setPowerLevel(newEventAddField.text, newEventPowerLevel.currentValue);
FormCard.FormComboBoxDelegate { newEventAddField.text = "";
text: i18n("Change the room canonical alias") }
description: "m.room.canonical_alias" }
textRole: "text" QQC2.ComboBox {
valueRole: "powerLevel" id: newEventPowerLevel
model: powerLevelModel focusPolicy: Qt.NoFocus // provided by parent
Component.onCompleted: currentIndex = indexOfValue(room.canonicalAliasPowerLevel) model: root.powerLevelModel
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) { textRole: "name"
room.canonicalAliasPowerLevel = currentValue; valueRole: "value"
} }
} QQC2.Button {
FormCard.FormComboBoxDelegate { id: addButton
text: i18n("Change the room topic")
description: "m.room.topic" text: i18n("Add keyword")
textRole: "text" Accessible.name: text
valueRole: "powerLevel" icon.name: "list-add"
model: powerLevelModel display: QQC2.AbstractButton.IconOnly
Component.onCompleted: currentIndex = indexOfValue(room.topicPowerLevel) enabled: newEventAddField.text.length > 0
onCurrentValueChanged: if (room.canSendState("m.room.power_levels")) {
room.topicPowerLevel = currentValue; onClicked: {
} root.permissionsModel.setPowerLevel(newEventAddField.text, newEventPowerLevel.currentValue);
} newEventAddField.text = "";
FormCard.FormComboBoxDelegate { }
text: i18n("Enable encryption for the room")
description: "m.room.encryption" QQC2.ToolTip {
textRole: "text" text: addButton.text
valueRole: "powerLevel" delay: Kirigami.Units.toolTipDelay
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;
} }
} }
} }