2018-01-05 01:27:32 +03:00
|
|
|
#include "Utils.h"
|
|
|
|
|
|
|
|
#include <variant.hpp>
|
|
|
|
|
|
|
|
using TimelineEvent = mtx::events::collections::TimelineEvents;
|
|
|
|
|
|
|
|
QString
|
|
|
|
utils::descriptiveTime(const QDateTime &then)
|
|
|
|
{
|
|
|
|
const auto now = QDateTime::currentDateTime();
|
|
|
|
const auto days = then.daysTo(now);
|
|
|
|
|
|
|
|
if (days == 0)
|
|
|
|
return then.toString("HH:mm");
|
|
|
|
else if (days < 2)
|
|
|
|
return QString("Yesterday");
|
|
|
|
else if (days < 365)
|
|
|
|
return then.toString("dd/MM");
|
|
|
|
|
|
|
|
return then.toString("dd/MM/yy");
|
|
|
|
}
|
|
|
|
|
|
|
|
DescInfo
|
2018-04-21 16:34:50 +03:00
|
|
|
utils::getMessageDescription(const TimelineEvent &event,
|
|
|
|
const QString &localUser,
|
|
|
|
const QString &room_id)
|
2018-01-05 01:27:32 +03:00
|
|
|
{
|
|
|
|
using Audio = mtx::events::RoomEvent<mtx::events::msg::Audio>;
|
|
|
|
using Emote = mtx::events::RoomEvent<mtx::events::msg::Emote>;
|
|
|
|
using File = mtx::events::RoomEvent<mtx::events::msg::File>;
|
|
|
|
using Image = mtx::events::RoomEvent<mtx::events::msg::Image>;
|
|
|
|
using Notice = mtx::events::RoomEvent<mtx::events::msg::Notice>;
|
|
|
|
using Text = mtx::events::RoomEvent<mtx::events::msg::Text>;
|
|
|
|
using Video = mtx::events::RoomEvent<mtx::events::msg::Video>;
|
|
|
|
|
|
|
|
if (mpark::holds_alternative<Audio>(event)) {
|
2018-04-29 15:42:40 +03:00
|
|
|
return createDescriptionInfo<Audio>(event, localUser, room_id);
|
2018-01-05 01:27:32 +03:00
|
|
|
} else if (mpark::holds_alternative<Emote>(event)) {
|
2018-04-29 15:42:40 +03:00
|
|
|
return createDescriptionInfo<Emote>(event, localUser, room_id);
|
2018-01-05 01:27:32 +03:00
|
|
|
} else if (mpark::holds_alternative<File>(event)) {
|
2018-04-29 15:42:40 +03:00
|
|
|
return createDescriptionInfo<File>(event, localUser, room_id);
|
2018-01-05 01:27:32 +03:00
|
|
|
} else if (mpark::holds_alternative<Image>(event)) {
|
2018-04-29 15:42:40 +03:00
|
|
|
return createDescriptionInfo<Image>(event, localUser, room_id);
|
2018-01-05 01:27:32 +03:00
|
|
|
} else if (mpark::holds_alternative<Notice>(event)) {
|
2018-04-29 15:42:40 +03:00
|
|
|
return createDescriptionInfo<Notice>(event, localUser, room_id);
|
2018-01-05 01:27:32 +03:00
|
|
|
} else if (mpark::holds_alternative<Text>(event)) {
|
2018-04-29 15:42:40 +03:00
|
|
|
return createDescriptionInfo<Text>(event, localUser, room_id);
|
2018-01-05 01:27:32 +03:00
|
|
|
} else if (mpark::holds_alternative<Video>(event)) {
|
2018-04-29 15:42:40 +03:00
|
|
|
return createDescriptionInfo<Video>(event, localUser, room_id);
|
2018-04-27 22:15:44 +03:00
|
|
|
} else if (mpark::holds_alternative<mtx::events::Sticker>(event)) {
|
2018-04-29 15:42:40 +03:00
|
|
|
return createDescriptionInfo<mtx::events::Sticker>(event, localUser, room_id);
|
2018-01-05 01:27:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return DescInfo{};
|
|
|
|
}
|
2018-01-12 11:21:53 +03:00
|
|
|
|
|
|
|
QString
|
|
|
|
utils::firstChar(const QString &input)
|
|
|
|
{
|
2018-01-25 19:10:05 +03:00
|
|
|
if (input.isEmpty())
|
|
|
|
return input;
|
2018-01-12 11:21:53 +03:00
|
|
|
|
2018-01-25 19:10:05 +03:00
|
|
|
for (auto const &c : input.toUcs4()) {
|
|
|
|
if (QString::fromUcs4(&c, 1) != QString("#"))
|
|
|
|
return QString::fromUcs4(&c, 1).toUpper();
|
|
|
|
}
|
|
|
|
|
|
|
|
return QString::fromUcs4(&input.toUcs4().at(0), 1).toUpper();
|
2018-01-12 11:21:53 +03:00
|
|
|
}
|
2018-02-18 23:52:31 +03:00
|
|
|
|
|
|
|
QString
|
2018-02-19 23:09:21 +03:00
|
|
|
utils::humanReadableFileSize(uint64_t bytes)
|
2018-02-18 23:52:31 +03:00
|
|
|
{
|
|
|
|
constexpr static const char *units[] = {"B", "KiB", "MiB", "GiB", "TiB"};
|
|
|
|
constexpr static const int length = sizeof(units) / sizeof(units[0]);
|
|
|
|
|
|
|
|
int u = 0;
|
|
|
|
double size = static_cast<double>(bytes);
|
|
|
|
while (size >= 1024.0 && u < length) {
|
|
|
|
++u;
|
|
|
|
size /= 1024.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return QString::number(size, 'g', 4) + ' ' + units[u];
|
|
|
|
}
|
2018-03-25 00:16:15 +03:00
|
|
|
|
|
|
|
int
|
|
|
|
utils::levenshtein_distance(const std::string &s1, const std::string &s2)
|
|
|
|
{
|
|
|
|
const int nlen = s1.size();
|
|
|
|
const int hlen = s2.size();
|
|
|
|
|
|
|
|
if (hlen == 0)
|
|
|
|
return -1;
|
|
|
|
if (nlen == 1)
|
|
|
|
return s2.find(s1);
|
|
|
|
|
|
|
|
std::vector<int> row1(hlen + 1, 0);
|
|
|
|
|
|
|
|
for (int i = 0; i < nlen; ++i) {
|
|
|
|
std::vector<int> row2(1, i + 1);
|
|
|
|
|
|
|
|
for (int j = 0; j < hlen; ++j) {
|
|
|
|
const int cost = s1[i] != s2[j];
|
|
|
|
row2.push_back(
|
|
|
|
std::min(row1[j + 1] + 1, std::min(row2[j] + 1, row1[j] + cost)));
|
|
|
|
}
|
|
|
|
|
|
|
|
row1.swap(row2);
|
|
|
|
}
|
|
|
|
|
|
|
|
return *std::min_element(row1.begin(), row1.end());
|
|
|
|
}
|
2018-05-05 16:38:41 +03:00
|
|
|
|
|
|
|
QString
|
|
|
|
utils::event_body(const mtx::events::collections::TimelineEvents &event)
|
|
|
|
{
|
|
|
|
using namespace mtx::events;
|
|
|
|
using namespace mtx::events::msg;
|
|
|
|
|
|
|
|
if (mpark::holds_alternative<RoomEvent<Audio>>(event)) {
|
|
|
|
return message_body<RoomEvent<Audio>>(event);
|
|
|
|
} else if (mpark::holds_alternative<RoomEvent<Emote>>(event)) {
|
|
|
|
return message_body<RoomEvent<Emote>>(event);
|
|
|
|
} else if (mpark::holds_alternative<RoomEvent<File>>(event)) {
|
|
|
|
return message_body<RoomEvent<File>>(event);
|
|
|
|
} else if (mpark::holds_alternative<RoomEvent<Image>>(event)) {
|
|
|
|
return message_body<RoomEvent<Image>>(event);
|
|
|
|
} else if (mpark::holds_alternative<RoomEvent<Notice>>(event)) {
|
|
|
|
return message_body<RoomEvent<Notice>>(event);
|
|
|
|
} else if (mpark::holds_alternative<Sticker>(event)) {
|
|
|
|
return message_body<Sticker>(event);
|
|
|
|
} else if (mpark::holds_alternative<RoomEvent<Text>>(event)) {
|
|
|
|
return message_body<RoomEvent<Text>>(event);
|
|
|
|
} else if (mpark::holds_alternative<RoomEvent<Video>>(event)) {
|
|
|
|
return message_body<RoomEvent<Video>>(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
return QString();
|
|
|
|
}
|