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

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;
};