2023-02-28 01:15:26 +00:00
|
|
|
// AUTOGENERATED COPYRIGHT HEADER START
|
|
|
|
// Copyright (C) 2020-2023 Michael Fabian 'Xaymar' Dirks <info@xaymar.com>
|
|
|
|
// Copyright (C) 2022 lainon <GermanAizek@yandex.ru>
|
|
|
|
// AUTOGENERATED COPYRIGHT HEADER END
|
2020-04-05 16:52:06 +00:00
|
|
|
|
|
|
|
#include "ui-about.hpp"
|
2022-08-28 12:28:37 +00:00
|
|
|
#include "ui-common.hpp"
|
2021-12-11 16:40:40 +00:00
|
|
|
#include "plugin.hpp"
|
2020-04-05 16:52:06 +00:00
|
|
|
#include "ui-about-entry.hpp"
|
2021-12-11 16:40:40 +00:00
|
|
|
#include "util/util-logging.hpp"
|
2020-04-05 16:52:06 +00:00
|
|
|
|
2022-08-29 10:29:44 +00:00
|
|
|
#include "warning-disable.hpp"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <deque>
|
|
|
|
#include <fstream>
|
|
|
|
#include <map>
|
2022-08-28 12:28:37 +00:00
|
|
|
#include <nlohmann/json.hpp>
|
2022-08-29 10:29:44 +00:00
|
|
|
#include <random>
|
|
|
|
#include "warning-enable.hpp"
|
2020-04-05 16:52:06 +00:00
|
|
|
|
2021-12-11 16:40:40 +00:00
|
|
|
#ifdef _DEBUG
|
|
|
|
#define ST_PREFIX "<%s> "
|
|
|
|
#define D_LOG_ERROR(x, ...) P_LOG_ERROR(ST_PREFIX##x, __FUNCTION_SIG__, __VA_ARGS__)
|
|
|
|
#define D_LOG_WARNING(x, ...) P_LOG_WARN(ST_PREFIX##x, __FUNCTION_SIG__, __VA_ARGS__)
|
|
|
|
#define D_LOG_INFO(x, ...) P_LOG_INFO(ST_PREFIX##x, __FUNCTION_SIG__, __VA_ARGS__)
|
|
|
|
#define D_LOG_DEBUG(x, ...) P_LOG_DEBUG(ST_PREFIX##x, __FUNCTION_SIG__, __VA_ARGS__)
|
|
|
|
#else
|
|
|
|
#define ST_PREFIX "<ui::about> "
|
|
|
|
#define D_LOG_ERROR(...) P_LOG_ERROR(ST_PREFIX __VA_ARGS__)
|
|
|
|
#define D_LOG_WARNING(...) P_LOG_WARN(ST_PREFIX __VA_ARGS__)
|
|
|
|
#define D_LOG_INFO(...) P_LOG_INFO(ST_PREFIX __VA_ARGS__)
|
|
|
|
#define D_LOG_DEBUG(...) P_LOG_DEBUG(ST_PREFIX __VA_ARGS__)
|
|
|
|
#endif
|
2020-04-05 16:52:06 +00:00
|
|
|
|
2020-05-30 23:10:18 +00:00
|
|
|
static const std::vector<std::string_view> _thankyous = {
|
|
|
|
":/thankyou/thankyou_cat",
|
|
|
|
":/thankyou/thankyou_otter",
|
|
|
|
":/thankyou/thankyou_fox",
|
|
|
|
};
|
|
|
|
|
2020-04-05 16:52:06 +00:00
|
|
|
streamfx::ui::about::about() : QDialog(reinterpret_cast<QWidget*>(obs_frontend_get_main_window()))
|
|
|
|
{
|
2021-12-11 16:40:40 +00:00
|
|
|
std::deque<ui::about::entry> entries;
|
2020-04-05 16:52:06 +00:00
|
|
|
|
2021-12-11 16:40:40 +00:00
|
|
|
// Set-up UI.
|
|
|
|
setupUi(this);
|
|
|
|
setWindowFlag(Qt::WindowContextHelpButtonHint, false); // Remove Help button.
|
|
|
|
content->setSizePolicy(QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Maximum);
|
2020-04-05 16:52:06 +00:00
|
|
|
|
2021-12-11 16:40:40 +00:00
|
|
|
// Create a uniform
|
2022-07-21 11:09:10 +00:00
|
|
|
std::random_device rd;
|
|
|
|
std::mt19937_64 generator(rd());
|
2021-12-11 16:40:40 +00:00
|
|
|
std::uniform_int_distribution<uint64_t> rnd;
|
|
|
|
|
|
|
|
// Load entries from 'thanks.json'
|
|
|
|
try {
|
|
|
|
auto file = streamfx::data_file_path("thanks.json");
|
|
|
|
D_LOG_DEBUG("Attempting to load '%s'...", file.generic_string().c_str());
|
|
|
|
if (!std::filesystem::exists(file)) {
|
|
|
|
// Crash if this file is missing.
|
|
|
|
throw std::runtime_error("File 'thanks.json' is missing.");
|
|
|
|
}
|
2020-05-30 23:10:18 +00:00
|
|
|
|
2021-12-11 16:40:40 +00:00
|
|
|
std::ifstream fils{file};
|
|
|
|
if (fils.bad() || fils.eof()) {
|
|
|
|
// Crash if this file is corrupt.
|
|
|
|
throw std::runtime_error("File 'thanks.json' is corrupted.");
|
|
|
|
}
|
2020-04-05 16:52:06 +00:00
|
|
|
|
2021-12-11 16:40:40 +00:00
|
|
|
auto data = nlohmann::json::parse(fils);
|
|
|
|
if (auto iter = data.find("contributor"); iter != data.end()) {
|
|
|
|
D_LOG_DEBUG(" Found %" PRIu64 " contributor entries.", iter->size());
|
|
|
|
auto kvs = iter->items();
|
|
|
|
for (auto kv : kvs) {
|
|
|
|
D_LOG_DEBUG(" '%s' => '%s'", kv.key().c_str(), kv.value().get<std::string>().c_str());
|
2023-05-13 12:35:46 +00:00
|
|
|
entries.push_back(ui::about::entry{kv.key(), role_type::CONTRIBUTOR, "", kv.value().get<std::string>()});
|
2020-04-05 16:52:06 +00:00
|
|
|
}
|
2021-12-11 16:40:40 +00:00
|
|
|
}
|
|
|
|
if (auto iter = data.find("translator"); iter != data.end()) {
|
|
|
|
D_LOG_DEBUG(" Found %" PRIu64 " translator entries.", iter->size());
|
|
|
|
auto kvs = iter->items();
|
|
|
|
for (auto kv : kvs) {
|
|
|
|
D_LOG_DEBUG(" '%s' => '%s'", kv.key().c_str(), kv.value().get<std::string>().c_str());
|
|
|
|
entries.push_back(ui::about::entry{kv.key(), role_type::TRANSLATOR, "", kv.value().get<std::string>()});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (auto iter = data.find("supporter"); iter != data.end()) {
|
|
|
|
auto data2 = *iter;
|
|
|
|
if (auto iter2 = data2.find("github"); iter2 != data2.end()) {
|
|
|
|
D_LOG_DEBUG(" Found %" PRIu64 " GitHub supporter entries.", iter2->size());
|
|
|
|
auto kvs = iter2->items();
|
|
|
|
for (auto kv : kvs) {
|
|
|
|
D_LOG_DEBUG(" '%s' => '%s'", kv.key().c_str(), kv.value().get<std::string>().c_str());
|
2023-05-13 12:35:46 +00:00
|
|
|
entries.push_back(ui::about::entry{kv.key(), role_type::SUPPORTER, "GitHub", kv.value().get<std::string>()});
|
2021-12-11 16:40:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (auto iter2 = data2.find("patreon"); iter2 != data2.end()) {
|
|
|
|
D_LOG_DEBUG(" Found %" PRIu64 " Patreon supporter entries.", iter2->size());
|
|
|
|
auto kvs = iter2->items();
|
|
|
|
for (auto kv : kvs) {
|
|
|
|
D_LOG_DEBUG(" '%s' => '%s'", kv.key().c_str(), kv.value().get<std::string>().c_str());
|
2023-05-13 12:35:46 +00:00
|
|
|
entries.push_back(ui::about::entry{kv.key(), role_type::SUPPORTER, "Patreon", kv.value().get<std::string>()});
|
2021-12-11 16:40:40 +00:00
|
|
|
}
|
2020-04-05 16:52:06 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-11 16:40:40 +00:00
|
|
|
} catch (const std::exception& ex) {
|
|
|
|
D_LOG_ERROR("Loading '%s' failed with error: %s", "thanks.json", ex.what());
|
|
|
|
throw std::runtime_error("File 'thanks.json' is invalid.");
|
2020-04-05 16:52:06 +00:00
|
|
|
}
|
2021-12-11 16:40:40 +00:00
|
|
|
|
|
|
|
// Build a grid of random entries.
|
2020-04-05 16:52:06 +00:00
|
|
|
{
|
2021-12-11 16:40:40 +00:00
|
|
|
QGridLayout* layout = dynamic_cast<QGridLayout*>(content->layout());
|
|
|
|
int row = 0;
|
|
|
|
int column = 0;
|
|
|
|
int thanks = 0;
|
|
|
|
|
|
|
|
// Fix columns being stretched for no reason.
|
|
|
|
layout->setColumnStretch(0, 1);
|
|
|
|
layout->setColumnStretch(1, 1);
|
|
|
|
|
2021-12-12 15:43:22 +00:00
|
|
|
D_LOG_DEBUG("Building grid of Thank You entries...", "");
|
|
|
|
|
2021-12-11 16:40:40 +00:00
|
|
|
// Randomize the list.
|
|
|
|
std::shuffle(entries.begin(), entries.end(), generator);
|
|
|
|
for (auto entry : entries) {
|
|
|
|
// Create a new entry.
|
|
|
|
streamfx::ui::about_entry* v = new streamfx::ui::about_entry(content, entry);
|
|
|
|
layout->addWidget(v, row, column);
|
|
|
|
layout->setRowStretch(row, 0);
|
|
|
|
|
2021-12-12 15:43:22 +00:00
|
|
|
D_LOG_DEBUG(" Added '%s' => '%s'.", entry.name.c_str(), entry.link.c_str());
|
|
|
|
|
2021-12-11 16:40:40 +00:00
|
|
|
// Proceed down the grid.
|
|
|
|
column += 1;
|
|
|
|
if (column >= 2) {
|
|
|
|
column = 0;
|
|
|
|
row += 1;
|
|
|
|
thanks += 1;
|
|
|
|
|
|
|
|
if (thanks % 9 == 8) { // "Thank you" every 8 rows.
|
|
|
|
auto image = new QLabel(content);
|
|
|
|
auto idx = rnd(generator) % _thankyous.size();
|
|
|
|
image->setPixmap(QPixmap(_thankyous.at(idx).data()));
|
|
|
|
image->setScaledContents(true);
|
|
|
|
image->setFixedSize(384, 384);
|
|
|
|
layout->addWidget(image, row, 0, 1, 2, Qt::AlignTop | Qt::AlignHCenter);
|
|
|
|
layout->setRowStretch(row, 0);
|
|
|
|
|
|
|
|
thanks = 0;
|
|
|
|
row += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{ // Fix weird automatic scaling done by Qt at the end of the list.
|
|
|
|
if (column != 0) {
|
|
|
|
row += 1;
|
|
|
|
column = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto padder = new QFrame(content);
|
|
|
|
auto sp = padder->sizePolicy();
|
2020-04-05 16:52:06 +00:00
|
|
|
sp.setVerticalPolicy(QSizePolicy::Minimum);
|
|
|
|
sp.setVerticalStretch(1);
|
|
|
|
padder->setSizePolicy(sp);
|
2021-12-11 16:40:40 +00:00
|
|
|
padder->setObjectName("PaddleMeDaddy");
|
|
|
|
padder->setMaximumHeight(QWIDGETSIZE_MAX);
|
|
|
|
padder->setMinimumHeight(1);
|
|
|
|
padder->setFrameShape(QFrame::NoFrame);
|
|
|
|
layout->addWidget(padder, row, 0, 1, 2);
|
|
|
|
layout->setRowStretch(row, std::numeric_limits<int>::max());
|
2020-04-05 16:52:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-12 03:23:57 +00:00
|
|
|
// Update the Version information.
|
|
|
|
version->setText(STREAMFX_VERSION_STRING);
|
|
|
|
|
2020-04-05 16:52:06 +00:00
|
|
|
// Make the OK button do things.
|
|
|
|
connect(buttonBox, &QDialogButtonBox::accepted, this, &streamfx::ui::about::on_ok);
|
|
|
|
}
|
|
|
|
|
|
|
|
streamfx::ui::about::~about() {}
|
|
|
|
|
|
|
|
void streamfx::ui::about::on_ok()
|
|
|
|
{
|
|
|
|
hide();
|
|
|
|
}
|