|
|
|
@ -532,6 +532,7 @@ TimelineModel::roleNames() const |
|
|
|
|
{IsOnlyEmoji, "isOnlyEmoji"}, |
|
|
|
|
{Body, "body"}, |
|
|
|
|
{FormattedBody, "formattedBody"}, |
|
|
|
|
{FormattedStateEvent, "formattedStateEvent"}, |
|
|
|
|
{IsSender, "isSender"}, |
|
|
|
|
{UserId, "userId"}, |
|
|
|
|
{UserName, "userName"}, |
|
|
|
@ -694,6 +695,76 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r |
|
|
|
|
|
|
|
|
|
return QVariant(utils::replaceEmoji(utils::linkifyMessage(formattedBody_))); |
|
|
|
|
} |
|
|
|
|
case FormattedStateEvent: { |
|
|
|
|
if (mtx::accessors::is_state_event(event)) { |
|
|
|
|
return std::visit( |
|
|
|
|
[this](const auto &e) { |
|
|
|
|
constexpr auto t = mtx::events::state_content_to_type<decltype(e.content)>; |
|
|
|
|
if constexpr (t == mtx::events::EventType::RoomServerAcl) |
|
|
|
|
return tr("%1 changed which servers are allowed in this room.") |
|
|
|
|
.arg(displayName(QString::fromStdString(e.sender))); |
|
|
|
|
else if constexpr (t == mtx::events::EventType::RoomName) { |
|
|
|
|
if (e.content.name.empty()) |
|
|
|
|
return tr("%1 removed the room name.") |
|
|
|
|
.arg(displayName(QString::fromStdString(e.sender))); |
|
|
|
|
else |
|
|
|
|
return tr("%1 changed the room name to: %2") |
|
|
|
|
.arg(displayName(QString::fromStdString(e.sender))) |
|
|
|
|
.arg(QString::fromStdString(e.content.name).toHtmlEscaped()); |
|
|
|
|
} else if constexpr (t == mtx::events::EventType::RoomTopic) { |
|
|
|
|
if (e.content.topic.empty()) |
|
|
|
|
return tr("%1 removed the topic.") |
|
|
|
|
.arg(displayName(QString::fromStdString(e.sender))); |
|
|
|
|
else |
|
|
|
|
return tr("%1 changed the topic to: %2") |
|
|
|
|
.arg(displayName(QString::fromStdString(e.sender))) |
|
|
|
|
.arg(QString::fromStdString(e.content.topic).toHtmlEscaped()); |
|
|
|
|
} else if constexpr (t == mtx::events::EventType::RoomAvatar) { |
|
|
|
|
if (e.content.url.starts_with("mxc://")) |
|
|
|
|
return tr("%1 changed the room avatar to: %2") |
|
|
|
|
.arg(displayName(QString::fromStdString(e.sender))) |
|
|
|
|
.arg(QStringLiteral("<img height=\"32\" src=\"%1\">") |
|
|
|
|
.arg(QUrl::toPercentEncoding( |
|
|
|
|
QString::fromStdString(e.content.url)))); |
|
|
|
|
else |
|
|
|
|
return tr("%1 removed the room avatar.") |
|
|
|
|
.arg(displayName(QString::fromStdString(e.sender))); |
|
|
|
|
} else if constexpr (t == mtx::events::EventType::RoomPinnedEvents) |
|
|
|
|
return tr("%1 changed the pinned messages.") |
|
|
|
|
.arg(displayName(QString::fromStdString(e.sender))); |
|
|
|
|
else if constexpr (t == mtx::events::EventType::ImagePackInRoom) |
|
|
|
|
formatImagePackEvent(e); |
|
|
|
|
else if constexpr (t == mtx::events::EventType::RoomCanonicalAlias) |
|
|
|
|
return tr("%1 changed the addresses for this room.") |
|
|
|
|
.arg(displayName(QString::fromStdString(e.sender))); |
|
|
|
|
else if constexpr (t == mtx::events::EventType::SpaceParent) |
|
|
|
|
return tr("%1 changed the parent communities for this room.") |
|
|
|
|
.arg(displayName(QString::fromStdString(e.sender))); |
|
|
|
|
else if constexpr (t == mtx::events::EventType::RoomCreate) |
|
|
|
|
return tr("%1 created and configured room: %2") |
|
|
|
|
.arg(displayName(QString::fromStdString(e.sender))) |
|
|
|
|
.arg(room_id_); |
|
|
|
|
else if constexpr (t == mtx::events::EventType::RoomPowerLevels) |
|
|
|
|
return formatPowerLevelEvent(e); |
|
|
|
|
else if constexpr (t == mtx::events::EventType::PolicyRuleRoom) |
|
|
|
|
return formatPolicyRule(QString::fromStdString(e.event_id)); |
|
|
|
|
else if constexpr (t == mtx::events::EventType::PolicyRuleUser) |
|
|
|
|
return formatPolicyRule(QString::fromStdString(e.event_id)); |
|
|
|
|
else if constexpr (t == mtx::events::EventType::PolicyRuleServer) |
|
|
|
|
return formatPolicyRule(QString::fromStdString(e.event_id)); |
|
|
|
|
else if constexpr (t == mtx::events::EventType::RoomHistoryVisibility) |
|
|
|
|
return formatHistoryVisibilityEvent(e); |
|
|
|
|
else if constexpr (t == mtx::events::EventType::RoomGuestAccess) |
|
|
|
|
return formatGuestAccessEvent(e); |
|
|
|
|
|
|
|
|
|
return tr("%1 changed unknown state event %2.") |
|
|
|
|
.arg(displayName(QString::fromStdString(e.sender))) |
|
|
|
|
.arg(QString::fromStdString(to_string(e.type))); |
|
|
|
|
}, |
|
|
|
|
event); |
|
|
|
|
} |
|
|
|
|
return QString(); |
|
|
|
|
} |
|
|
|
|
case Url: |
|
|
|
|
return QVariant(QString::fromStdString(url(event))); |
|
|
|
|
case ThumbnailUrl: |
|
|
|
@ -2308,20 +2379,13 @@ TimelineModel::formatJoinRuleEvent(const QString &id) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QString |
|
|
|
|
TimelineModel::formatGuestAccessEvent(const QString &id) |
|
|
|
|
TimelineModel::formatGuestAccessEvent( |
|
|
|
|
const mtx::events::StateEvent<mtx::events::state::GuestAccess> &event) const |
|
|
|
|
{ |
|
|
|
|
auto e = events.get(id.toStdString(), ""); |
|
|
|
|
if (!e) |
|
|
|
|
return {}; |
|
|
|
|
|
|
|
|
|
auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::GuestAccess>>(e); |
|
|
|
|
if (!event) |
|
|
|
|
return {}; |
|
|
|
|
|
|
|
|
|
QString user = QString::fromStdString(event->sender); |
|
|
|
|
QString user = QString::fromStdString(event.sender); |
|
|
|
|
QString name = utils::replaceEmoji(displayName(user)); |
|
|
|
|
|
|
|
|
|
switch (event->content.guest_access) { |
|
|
|
|
switch (event.content.guest_access) { |
|
|
|
|
case mtx::events::state::AccessState::CanJoin: |
|
|
|
|
return tr("%1 made the room open to guests.").arg(name); |
|
|
|
|
case mtx::events::state::AccessState::Forbidden: |
|
|
|
@ -2332,21 +2396,13 @@ TimelineModel::formatGuestAccessEvent(const QString &id) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QString |
|
|
|
|
TimelineModel::formatHistoryVisibilityEvent(const QString &id) |
|
|
|
|
TimelineModel::formatHistoryVisibilityEvent( |
|
|
|
|
const mtx::events::StateEvent<mtx::events::state::HistoryVisibility> &event) const |
|
|
|
|
{ |
|
|
|
|
auto e = events.get(id.toStdString(), ""); |
|
|
|
|
if (!e) |
|
|
|
|
return {}; |
|
|
|
|
|
|
|
|
|
auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::HistoryVisibility>>(e); |
|
|
|
|
|
|
|
|
|
if (!event) |
|
|
|
|
return {}; |
|
|
|
|
|
|
|
|
|
QString user = QString::fromStdString(event->sender); |
|
|
|
|
QString user = QString::fromStdString(event.sender); |
|
|
|
|
QString name = utils::replaceEmoji(displayName(user)); |
|
|
|
|
|
|
|
|
|
switch (event->content.history_visibility) { |
|
|
|
|
switch (event.content.history_visibility) { |
|
|
|
|
case mtx::events::state::Visibility::WorldReadable: |
|
|
|
|
return tr("%1 made the room history world readable. Events may be now read by " |
|
|
|
|
"non-joined people.") |
|
|
|
@ -2364,32 +2420,25 @@ TimelineModel::formatHistoryVisibilityEvent(const QString &id) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QString |
|
|
|
|
TimelineModel::formatPowerLevelEvent(const QString &id) |
|
|
|
|
TimelineModel::formatPowerLevelEvent( |
|
|
|
|
const mtx::events::StateEvent<mtx::events::state::PowerLevels> &event) const |
|
|
|
|
{ |
|
|
|
|
auto e = events.get(id.toStdString(), ""); |
|
|
|
|
if (!e) |
|
|
|
|
return {}; |
|
|
|
|
|
|
|
|
|
auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::PowerLevels>>(e); |
|
|
|
|
if (!event) |
|
|
|
|
return QString(); |
|
|
|
|
|
|
|
|
|
mtx::events::StateEvent<mtx::events::state::PowerLevels> const *prevEvent = nullptr; |
|
|
|
|
if (!event->unsigned_data.replaces_state.empty()) { |
|
|
|
|
auto tempPrevEvent = events.get(event->unsigned_data.replaces_state, event->event_id); |
|
|
|
|
if (!event.unsigned_data.replaces_state.empty()) { |
|
|
|
|
auto tempPrevEvent = events.get(event.unsigned_data.replaces_state, event.event_id); |
|
|
|
|
if (tempPrevEvent) { |
|
|
|
|
prevEvent = |
|
|
|
|
std::get_if<mtx::events::StateEvent<mtx::events::state::PowerLevels>>(tempPrevEvent); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QString user = QString::fromStdString(event->sender); |
|
|
|
|
QString user = QString::fromStdString(event.sender); |
|
|
|
|
QString sender_name = utils::replaceEmoji(displayName(user)); |
|
|
|
|
// Get the rooms levels for redactions and powerlevel changes to determine "Administrator" and
|
|
|
|
|
// "Moderator" powerlevels.
|
|
|
|
|
auto administrator_power_level = event->content.state_level("m.room.power_levels"); |
|
|
|
|
auto moderator_power_level = event->content.redact; |
|
|
|
|
auto default_powerlevel = event->content.users_default; |
|
|
|
|
auto administrator_power_level = event.content.state_level("m.room.power_levels"); |
|
|
|
|
auto moderator_power_level = event.content.redact; |
|
|
|
|
auto default_powerlevel = event.content.users_default; |
|
|
|
|
if (!prevEvent) |
|
|
|
|
return tr("%1 has changed the room's permissions.").arg(sender_name); |
|
|
|
|
|
|
|
|
@ -2399,7 +2448,7 @@ TimelineModel::formatPowerLevelEvent(const QString &id) |
|
|
|
|
auto numberOfAffected = 0; |
|
|
|
|
// We do only compare to people with explicit PL. Usually others are not going to be
|
|
|
|
|
// affected either way and this is cheaper to iterate over.
|
|
|
|
|
for (auto const &[mxid, currentPowerlevel] : event->content.users) { |
|
|
|
|
for (auto const &[mxid, currentPowerlevel] : event.content.users) { |
|
|
|
|
if (currentPowerlevel == newPowerlevelSetting && |
|
|
|
|
prevEvent->content.user_level(mxid) < newPowerlevelSetting) { |
|
|
|
|
numberOfAffected++; |
|
|
|
@ -2413,16 +2462,16 @@ TimelineModel::formatPowerLevelEvent(const QString &id) |
|
|
|
|
|
|
|
|
|
QStringList resultingMessage{}; |
|
|
|
|
// These affect only a few people. Therefor we can print who is affected.
|
|
|
|
|
if (event->content.kick != prevEvent->content.kick) { |
|
|
|
|
if (event.content.kick != prevEvent->content.kick) { |
|
|
|
|
auto default_message = tr("%1 has changed the room's kick powerlevel from %2 to %3.") |
|
|
|
|
.arg(sender_name) |
|
|
|
|
.arg(prevEvent->content.kick) |
|
|
|
|
.arg(event->content.kick); |
|
|
|
|
.arg(event.content.kick); |
|
|
|
|
|
|
|
|
|
// We only calculate affected users if we change to a level above the default users PL
|
|
|
|
|
// to not accidentally have a DoS vector
|
|
|
|
|
if (event->content.kick > default_powerlevel) { |
|
|
|
|
auto [affected, number_of_affected] = calc_affected(event->content.kick); |
|
|
|
|
if (event.content.kick > default_powerlevel) { |
|
|
|
|
auto [affected, number_of_affected] = calc_affected(event.content.kick); |
|
|
|
|
|
|
|
|
|
if (number_of_affected != 0) { |
|
|
|
|
auto true_affected_rest = number_of_affected - affected.size(); |
|
|
|
@ -2444,16 +2493,16 @@ TimelineModel::formatPowerLevelEvent(const QString &id) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (event->content.redact != prevEvent->content.redact) { |
|
|
|
|
if (event.content.redact != prevEvent->content.redact) { |
|
|
|
|
auto default_message = tr("%1 has changed the room's redact powerlevel from %2 to %3.") |
|
|
|
|
.arg(sender_name) |
|
|
|
|
.arg(prevEvent->content.redact) |
|
|
|
|
.arg(event->content.redact); |
|
|
|
|
.arg(event.content.redact); |
|
|
|
|
|
|
|
|
|
// We only calculate affected users if we change to a level above the default users PL
|
|
|
|
|
// to not accidentally have a DoS vector
|
|
|
|
|
if (event->content.redact > default_powerlevel) { |
|
|
|
|
auto [affected, number_of_affected] = calc_affected(event->content.redact); |
|
|
|
|
if (event.content.redact > default_powerlevel) { |
|
|
|
|
auto [affected, number_of_affected] = calc_affected(event.content.redact); |
|
|
|
|
|
|
|
|
|
if (number_of_affected != 0) { |
|
|
|
|
auto true_affected_rest = number_of_affected - affected.size(); |
|
|
|
@ -2476,16 +2525,16 @@ TimelineModel::formatPowerLevelEvent(const QString &id) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (event->content.ban != prevEvent->content.ban) { |
|
|
|
|
if (event.content.ban != prevEvent->content.ban) { |
|
|
|
|
auto default_message = tr("%1 has changed the room's ban powerlevel from %2 to %3.") |
|
|
|
|
.arg(sender_name) |
|
|
|
|
.arg(prevEvent->content.ban) |
|
|
|
|
.arg(event->content.ban); |
|
|
|
|
.arg(event.content.ban); |
|
|
|
|
|
|
|
|
|
// We only calculate affected users if we change to a level above the default users PL
|
|
|
|
|
// to not accidentally have a DoS vector
|
|
|
|
|
if (event->content.ban > default_powerlevel) { |
|
|
|
|
auto [affected, number_of_affected] = calc_affected(event->content.ban); |
|
|
|
|
if (event.content.ban > default_powerlevel) { |
|
|
|
|
auto [affected, number_of_affected] = calc_affected(event.content.ban); |
|
|
|
|
|
|
|
|
|
if (number_of_affected != 0) { |
|
|
|
|
auto true_affected_rest = number_of_affected - affected.size(); |
|
|
|
@ -2507,17 +2556,17 @@ TimelineModel::formatPowerLevelEvent(const QString &id) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (event->content.state_default != prevEvent->content.state_default) { |
|
|
|
|
if (event.content.state_default != prevEvent->content.state_default) { |
|
|
|
|
auto default_message = |
|
|
|
|
tr("%1 has changed the room's state_default powerlevel from %2 to %3.") |
|
|
|
|
.arg(sender_name) |
|
|
|
|
.arg(prevEvent->content.state_default) |
|
|
|
|
.arg(event->content.state_default); |
|
|
|
|
.arg(event.content.state_default); |
|
|
|
|
|
|
|
|
|
// We only calculate affected users if we change to a level above the default users PL
|
|
|
|
|
// to not accidentally have a DoS vector
|
|
|
|
|
if (event->content.state_default > default_powerlevel) { |
|
|
|
|
auto [affected, number_of_affected] = calc_affected(event->content.kick); |
|
|
|
|
if (event.content.state_default > default_powerlevel) { |
|
|
|
|
auto [affected, number_of_affected] = calc_affected(event.content.kick); |
|
|
|
|
|
|
|
|
|
if (number_of_affected != 0) { |
|
|
|
|
auto true_affected_rest = number_of_affected - affected.size(); |
|
|
|
@ -2541,42 +2590,42 @@ TimelineModel::formatPowerLevelEvent(const QString &id) |
|
|
|
|
|
|
|
|
|
// These affect potentially the whole room. We there for do not calculate who gets affected
|
|
|
|
|
// by this to prevent huge lists of people.
|
|
|
|
|
if (event->content.invite != prevEvent->content.invite) { |
|
|
|
|
if (event.content.invite != prevEvent->content.invite) { |
|
|
|
|
resultingMessage.append(tr("%1 has changed the room's invite powerlevel from %2 to %3.") |
|
|
|
|
.arg(sender_name, |
|
|
|
|
QString::number(prevEvent->content.invite), |
|
|
|
|
QString::number(event->content.invite))); |
|
|
|
|
QString::number(event.content.invite))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (event->content.events_default != prevEvent->content.events_default) { |
|
|
|
|
if ((event->content.events_default > default_powerlevel) && |
|
|
|
|
if (event.content.events_default != prevEvent->content.events_default) { |
|
|
|
|
if ((event.content.events_default > default_powerlevel) && |
|
|
|
|
prevEvent->content.events_default <= default_powerlevel) { |
|
|
|
|
resultingMessage.append( |
|
|
|
|
tr("%1 has changed the room's events_default powerlevel from %2 to %3. New " |
|
|
|
|
"users can now not send any events.") |
|
|
|
|
.arg(sender_name, |
|
|
|
|
QString::number(prevEvent->content.events_default), |
|
|
|
|
QString::number(event->content.events_default))); |
|
|
|
|
} else if ((event->content.events_default < prevEvent->content.events_default) && |
|
|
|
|
(event->content.events_default < default_powerlevel) && |
|
|
|
|
QString::number(event.content.events_default))); |
|
|
|
|
} else if ((event.content.events_default < prevEvent->content.events_default) && |
|
|
|
|
(event.content.events_default < default_powerlevel) && |
|
|
|
|
(prevEvent->content.events_default > default_powerlevel)) { |
|
|
|
|
resultingMessage.append( |
|
|
|
|
tr("%1 has changed the room's events_default powerlevel from %2 to %3. New " |
|
|
|
|
"users can now send events that are not otherwise restricted.") |
|
|
|
|
.arg(sender_name, |
|
|
|
|
QString::number(prevEvent->content.events_default), |
|
|
|
|
QString::number(event->content.events_default))); |
|
|
|
|
QString::number(event.content.events_default))); |
|
|
|
|
} else { |
|
|
|
|
resultingMessage.append( |
|
|
|
|
tr("%1 has changed the room's events_default powerlevel from %2 to %3.") |
|
|
|
|
.arg(sender_name, |
|
|
|
|
QString::number(prevEvent->content.events_default), |
|
|
|
|
QString::number(event->content.events_default))); |
|
|
|
|
QString::number(event.content.events_default))); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Compare if a Powerlevel of a user changed
|
|
|
|
|
for (auto const &[mxid, powerlevel] : event->content.users) { |
|
|
|
|
for (auto const &[mxid, powerlevel] : event.content.users) { |
|
|
|
|
auto nameOfChangedUser = utils::replaceEmoji(displayName(QString::fromStdString(mxid))); |
|
|
|
|
if (prevEvent->content.user_level(mxid) != powerlevel) { |
|
|
|
|
if (powerlevel >= administrator_power_level) { |
|
|
|
@ -2601,7 +2650,7 @@ TimelineModel::formatPowerLevelEvent(const QString &id) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Handle added/removed/changed event type
|
|
|
|
|
for (auto const &[event_type, powerlevel] : event->content.events) { |
|
|
|
|
for (auto const &[event_type, powerlevel] : event.content.events) { |
|
|
|
|
auto prev_not_present = |
|
|
|
|
prevEvent->content.events.find(event_type) == prevEvent->content.events.end(); |
|
|
|
|
|
|
|
|
@ -2640,26 +2689,19 @@ TimelineModel::formatPowerLevelEvent(const QString &id) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QString |
|
|
|
|
TimelineModel::formatImagePackEvent(const QString &id) |
|
|
|
|
TimelineModel::formatImagePackEvent( |
|
|
|
|
const mtx::events::StateEvent<mtx::events::msc2545::ImagePack> &event) const |
|
|
|
|
{ |
|
|
|
|
auto e = events.get(id.toStdString(), ""); |
|
|
|
|
if (!e) |
|
|
|
|
return {}; |
|
|
|
|
|
|
|
|
|
auto event = std::get_if<mtx::events::StateEvent<mtx::events::msc2545::ImagePack>>(e); |
|
|
|
|
if (!event) |
|
|
|
|
return {}; |
|
|
|
|
|
|
|
|
|
mtx::events::StateEvent<mtx::events::msc2545::ImagePack> const *prevEvent = nullptr; |
|
|
|
|
if (!event->unsigned_data.replaces_state.empty()) { |
|
|
|
|
auto tempPrevEvent = events.get(event->unsigned_data.replaces_state, event->event_id); |
|
|
|
|
if (!event.unsigned_data.replaces_state.empty()) { |
|
|
|
|
auto tempPrevEvent = events.get(event.unsigned_data.replaces_state, event.event_id); |
|
|
|
|
if (tempPrevEvent) { |
|
|
|
|
prevEvent = |
|
|
|
|
std::get_if<mtx::events::StateEvent<mtx::events::msc2545::ImagePack>>(tempPrevEvent); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const auto &newImages = event->content.images; |
|
|
|
|
const auto &newImages = event.content.images; |
|
|
|
|
const auto oldImages = prevEvent ? prevEvent->content.images : decltype(newImages){}; |
|
|
|
|
|
|
|
|
|
auto ascent = QFontMetrics(UserSettings::instance()->font()).ascent(); |
|
|
|
@ -2682,12 +2724,12 @@ TimelineModel::formatImagePackEvent(const QString &id) |
|
|
|
|
auto added = calcChange(newImages, oldImages); |
|
|
|
|
auto removed = calcChange(oldImages, newImages); |
|
|
|
|
|
|
|
|
|
auto sender = utils::replaceEmoji(displayName(QString::fromStdString(event->sender))); |
|
|
|
|
auto sender = utils::replaceEmoji(displayName(QString::fromStdString(event.sender))); |
|
|
|
|
const auto packId = [&event]() -> QString { |
|
|
|
|
if (event->content.pack && !event->content.pack->display_name.empty()) { |
|
|
|
|
return event->content.pack->display_name.c_str(); |
|
|
|
|
} else if (!event->state_key.empty()) { |
|
|
|
|
return event->state_key.c_str(); |
|
|
|
|
if (event.content.pack && !event.content.pack->display_name.empty()) { |
|
|
|
|
return event.content.pack->display_name.c_str(); |
|
|
|
|
} else if (!event.state_key.empty()) { |
|
|
|
|
return event.state_key.c_str(); |
|
|
|
|
} |
|
|
|
|
return tr("(empty)"); |
|
|
|
|
}(); |
|
|
|
@ -2712,7 +2754,7 @@ TimelineModel::formatImagePackEvent(const QString &id) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QString |
|
|
|
|
TimelineModel::formatPolicyRule(const QString &id) |
|
|
|
|
TimelineModel::formatPolicyRule(const QString &id) const |
|
|
|
|
{ |
|
|
|
|
auto idStr = id.toStdString(); |
|
|
|
|
auto e = events.get(idStr, ""); |
|
|
|
|