// SPDX-FileCopyrightText: Nheko Contributors
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "PowerlevelsEditModels.h"
#include <QCoreApplication>
#include <QTimer>
#include <algorithm>
#include <set>
#include <unordered_set>
#include "Cache.h"
#include "Cache_p.h"
#include "ChatPage.h"
#include "Logging.h"
#include "MatrixClient.h"
PowerlevelsTypeListModel::PowerlevelsTypeListModel(const std::string &rid,
const mtx::events::state::PowerLevels &pl,
QObject *parent)
: QAbstractListModel(parent)
, room_id(rid)
, powerLevels_(pl)
{
std::set<mtx::events::state::power_level_t> seen_levels;
for (const auto &[type, level] : powerLevels_.events) {
if (!seen_levels.count(level)) {
types.push_back(Entry{"", level});
seen_levels.insert(level);
}
types.push_back(Entry{type, level});
}
for (const auto &[user, level] : powerLevels_.users) {
(void)user;
if (!seen_levels.count(level)) {
types.push_back(Entry{"", level});
seen_levels.insert(level);
}
}
for (const auto &level : {
powerLevels_.events_default,
powerLevels_.state_default,
powerLevels_.users_default,
powerLevels_.ban,
powerLevels_.kick,
powerLevels_.invite,
powerLevels_.redact,
}) {
if (!seen_levels.count(level)) {
types.push_back(Entry{"", level});
seen_levels.insert(level);
}
}
types.push_back(Entry{"zdefault_states", powerLevels_.state_default});
types.push_back(Entry{"zdefault_events", powerLevels_.events_default});
types.push_back(Entry{"ban", powerLevels_.ban});
types.push_back(Entry{"kick", powerLevels_.kick});
types.push_back(Entry{"invite", powerLevels_.invite});
types.push_back(Entry{"redact", powerLevels_.redact});
std::sort(types.begin(), types.end(), [](const Entry &a, const Entry &b) {
if (a.pl != b.pl) // sort by PL
return a.pl > b.pl;
else if (a.type.empty() != b.type.empty()) // empty types are headers
return a.type.empty() > b.type.empty();
else {
bool a_contains_dot = a.type.find('.') != std::string::npos;
bool b_contains_dot = b.type.find('.') != std::string::npos;
if (a_contains_dot != b_contains_dot) // sort stuff like "invite" or "default" last
return a_contains_dot > b_contains_dot;
else // rest is sorted alphabetical
return a.type < b.type;
}
});
}
std::map<std::string, mtx::events::state::power_level_t, std::less<>>
PowerlevelsTypeListModel::toEvents() const
{
std::map<std::string, mtx::events::state::power_level_t, std::less<>> m;
for (const auto &[key, pl] : std::as_const(types))
if (key.find('.') != std::string::npos)
m[key] = pl;
return m;
}
mtx::events::state::power_level_t
PowerlevelsTypeListModel::kick() const
{
for (const auto &[key, pl] : std::as_const(types))
if (key == "kick")
return pl;
return powerLevels_.users_default;
}
mtx::events::state::power_level_t
PowerlevelsTypeListModel::invite() const
{
for (const auto &[key, pl] : std::as_const(types))
if (key == "invite")
return pl;
return powerLevels_.users_default;
}
mtx::events::state::power_level_t
PowerlevelsTypeListModel::ban() const
{
for (const auto &[key, pl] : std::as_const(types))
if (key == "ban")
return pl;
return powerLevels_.users_default;
}
mtx::events::state::power_level_t
PowerlevelsTypeListModel::eventsDefault() const
{
for (const