project: Implement a brand new UI with fancy windows
Implements support for various new UI features that weren't possible up until now, such as an 'About StreamFX' window with a thank you to everyone that supported the project up until now.
|
|
@ -501,8 +501,21 @@ endif()
|
||||||
## OBS Studio - Frontend/Qt
|
## OBS Studio - Frontend/Qt
|
||||||
if(HAVE_OBS_FRONTEND)
|
if(HAVE_OBS_FRONTEND)
|
||||||
list(APPEND PROJECT_UI
|
list(APPEND PROJECT_UI
|
||||||
|
"ui/streamfx.qrc"
|
||||||
|
"ui/about.ui"
|
||||||
|
"ui/about-entry.ui"
|
||||||
)
|
)
|
||||||
list(APPEND PROJECT_PRIVATE_SOURCE
|
list(APPEND PROJECT_PRIVATE_SOURCE
|
||||||
|
"source/ui/ui-common.hpp"
|
||||||
|
"source/ui/ui.hpp"
|
||||||
|
"source/ui/ui.cpp"
|
||||||
|
"source/ui/ui-about.hpp"
|
||||||
|
"source/ui/ui-about.cpp"
|
||||||
|
"source/ui/ui-about-entry.hpp"
|
||||||
|
"source/ui/ui-about-entry.cpp"
|
||||||
|
)
|
||||||
|
list(APPEND PROJECT_DATA
|
||||||
|
|
||||||
)
|
)
|
||||||
list(APPEND PROJECT_INCLUDE_DIRS
|
list(APPEND PROJECT_INCLUDE_DIRS
|
||||||
"source/ui"
|
"source/ui"
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "plugin.hpp"
|
#include "plugin.hpp"
|
||||||
|
#include <fstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include "configuration.hpp"
|
#include "configuration.hpp"
|
||||||
#include "obs/obs-source-tracker.hpp"
|
#include "obs/obs-source-tracker.hpp"
|
||||||
|
|
@ -62,6 +63,10 @@
|
||||||
#include "transitions/transition-shader.hpp"
|
#include "transitions/transition-shader.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_FRONTEND
|
||||||
|
#include "ui/ui.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
static std::shared_ptr<util::threadpool> _threadpool;
|
static std::shared_ptr<util::threadpool> _threadpool;
|
||||||
|
|
||||||
MODULE_EXPORT bool obs_module_load(void)
|
MODULE_EXPORT bool obs_module_load(void)
|
||||||
|
|
@ -133,6 +138,11 @@ try {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Frontend
|
||||||
|
#ifdef ENABLE_FRONTEND
|
||||||
|
streamfx::ui::handler::initialize();
|
||||||
|
#endif
|
||||||
|
|
||||||
LOG_INFO("Loaded Version %s", STREAMFX_VERSION_STRING);
|
LOG_INFO("Loaded Version %s", STREAMFX_VERSION_STRING);
|
||||||
return true;
|
return true;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
|
@ -144,6 +154,11 @@ MODULE_EXPORT void obs_module_unload(void)
|
||||||
try {
|
try {
|
||||||
LOG_INFO("Unloading Version %s", STREAMFX_VERSION_STRING);
|
LOG_INFO("Unloading Version %s", STREAMFX_VERSION_STRING);
|
||||||
|
|
||||||
|
// Frontend
|
||||||
|
#ifdef ENABLE_FRONTEND
|
||||||
|
streamfx::ui::handler::finalize();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Transitions
|
// Transitions
|
||||||
{
|
{
|
||||||
using namespace streamfx::transition;
|
using namespace streamfx::transition;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* Modern effects for a modern Streamer
|
||||||
|
* Copyright (C) 2020 Michael Fabian Dirks
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ui-about-entry.hpp"
|
||||||
|
|
||||||
|
constexpr std::string_view i18n_role_contributor = "UI.About.Role.Contributor";
|
||||||
|
constexpr std::string_view i18n_role_translator = "UI.About.Role.Translator";
|
||||||
|
constexpr std::string_view i18n_role_family = "UI.About.Role.Family";
|
||||||
|
constexpr std::string_view i18n_role_friend = "UI.About.Role.Friend";
|
||||||
|
constexpr std::string_view i18n_role_supporter_patreon = "UI.About.Role.Supporter.Patreon";
|
||||||
|
constexpr std::string_view i18n_role_supporter_github = "UI.About.Role.Supporter.Github";
|
||||||
|
constexpr std::string_view i18n_role_supporter_twitch = "UI.About.Role.Supporter.Twitch";
|
||||||
|
constexpr std::string_view i18n_role_creator = "UI.About.Role.Creator";
|
||||||
|
|
||||||
|
streamfx::ui::about_entry::about_entry(QWidget* parent, streamfx::ui::about::entry& entry)
|
||||||
|
: QWidget(parent), _last_click(std::chrono::high_resolution_clock::now()), _link1_url(), _link2_url()
|
||||||
|
{
|
||||||
|
setupUi(this);
|
||||||
|
|
||||||
|
name->setText(QString::fromStdString(entry.name));
|
||||||
|
switch (entry.role) {
|
||||||
|
case streamfx::ui::about::role_type::NONE:
|
||||||
|
title->setText(QString::fromStdString(entry.role_custom));
|
||||||
|
break;
|
||||||
|
case streamfx::ui::about::role_type::CONTRIBUTOR:
|
||||||
|
title->setText(D_TRANSLATE(i18n_role_contributor.data()));
|
||||||
|
break;
|
||||||
|
case streamfx::ui::about::role_type::TRANSLATOR:
|
||||||
|
title->setText(D_TRANSLATE(i18n_role_translator.data()));
|
||||||
|
break;
|
||||||
|
case streamfx::ui::about::role_type::FAMILY: {
|
||||||
|
const char* txt = D_TRANSLATE(i18n_role_family.data());
|
||||||
|
std::vector<char> buf(2048);
|
||||||
|
snprintf(buf.data(), buf.size(), txt, entry.role_custom.c_str());
|
||||||
|
title->setText(QString::fromUtf8(buf.data()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case streamfx::ui::about::role_type::FRIEND: {
|
||||||
|
const char* txt = D_TRANSLATE(i18n_role_friend.data());
|
||||||
|
std::vector<char> buf(2048);
|
||||||
|
snprintf(buf.data(), buf.size(), txt, entry.role_custom.c_str());
|
||||||
|
title->setText(QString::fromUtf8(buf.data()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case streamfx::ui::about::role_type::PATREON_SUPPORTER:
|
||||||
|
title->setText(D_TRANSLATE(i18n_role_supporter_patreon.data()));
|
||||||
|
break;
|
||||||
|
case streamfx::ui::about::role_type::GITHUB_SUPPORTER:
|
||||||
|
title->setText(D_TRANSLATE(i18n_role_supporter_github.data()));
|
||||||
|
break;
|
||||||
|
case streamfx::ui::about::role_type::TWITCH_SUPPORTER:
|
||||||
|
title->setText(D_TRANSLATE(i18n_role_supporter_twitch.data()));
|
||||||
|
break;
|
||||||
|
case streamfx::ui::about::role_type::CREATOR:
|
||||||
|
title->setText(D_TRANSLATE(i18n_role_creator.data()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<streamfx::ui::about::link_type, std::string, std::string, QPushButton*, QUrl&> els[]{
|
||||||
|
{entry.link1_type, entry.link1_address, entry.link1_text, link1, _link1_url},
|
||||||
|
{entry.link2_type, entry.link2_address, entry.link2_text, link2, _link2_url},
|
||||||
|
};
|
||||||
|
for (auto el : els) {
|
||||||
|
switch (std::get<0>(el)) {
|
||||||
|
case streamfx::ui::about::link_type::NONE:
|
||||||
|
std::get<3>(el)->setHidden(true);
|
||||||
|
break;
|
||||||
|
case streamfx::ui::about::link_type::GENERIC:
|
||||||
|
std::get<3>(el)->setIcon(QIcon(":/linktype/generic"));
|
||||||
|
break;
|
||||||
|
case streamfx::ui::about::link_type::SOCIAL_TWITCH:
|
||||||
|
std::get<3>(el)->setIcon(QIcon(":/linktype/twitch"));
|
||||||
|
break;
|
||||||
|
case streamfx::ui::about::link_type::SOCIAL_YOUTUBE:
|
||||||
|
std::get<3>(el)->setIcon(QIcon(":/linktype/youtube"));
|
||||||
|
break;
|
||||||
|
case streamfx::ui::about::link_type::SOCIAL_DISCORD:
|
||||||
|
std::get<3>(el)->setIcon(QIcon(":/linktype/discord"));
|
||||||
|
break;
|
||||||
|
case streamfx::ui::about::link_type::SOCIAL_TWITTER:
|
||||||
|
std::get<3>(el)->setIcon(QIcon(":/linktype/twitter"));
|
||||||
|
break;
|
||||||
|
case streamfx::ui::about::link_type::SOCIAL_FACEBOOK:
|
||||||
|
std::get<3>(el)->setIcon(QIcon(":/linktype/facebook"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::get<3>(el)->setText(QString::fromUtf8(std::get<2>(el).c_str()));
|
||||||
|
std::get<4>(el).setUrl(QString::fromStdString(std::get<1>(el)));
|
||||||
|
}
|
||||||
|
connect(link1, &QPushButton::pressed, this, &streamfx::ui::about_entry::on_link1_clicked);
|
||||||
|
connect(link2, &QPushButton::pressed, this, &streamfx::ui::about_entry::on_link2_clicked);
|
||||||
|
|
||||||
|
// Don't free up space when hidden.
|
||||||
|
/*if (!(link1->isVisible() || link2->isVisible())) {
|
||||||
|
QSizePolicy qsp = link1->sizePolicy();
|
||||||
|
qsp.setRetainSizeWhenHidden(true);
|
||||||
|
link1->setSizePolicy(qsp);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
streamfx::ui::about_entry::~about_entry() {}
|
||||||
|
|
||||||
|
void streamfx::ui::about_entry::on_link1_clicked()
|
||||||
|
{
|
||||||
|
// FIXME! Button clicks twice?
|
||||||
|
for (size_t attempt = 0; (attempt < 10) && (!QDesktopServices::openUrl(_link1_url)); attempt++) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void streamfx::ui::about_entry::on_link2_clicked()
|
||||||
|
{
|
||||||
|
for (size_t attempt = 0; (attempt < 10) && (!QDesktopServices::openUrl(_link2_url)); attempt++) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Modern effects for a modern Streamer
|
||||||
|
* Copyright (C) 2020 Michael Fabian Dirks
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <chrono>
|
||||||
|
#include "ui-about.hpp"
|
||||||
|
#include "ui-common.hpp"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251 4365 4371 4619 4946)
|
||||||
|
#endif
|
||||||
|
#include "ui_about-entry.h"
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace streamfx::ui {
|
||||||
|
class about_entry : public QWidget, public Ui::AboutEntry {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::chrono::high_resolution_clock::time_point _last_click;
|
||||||
|
QUrl _link1_url;
|
||||||
|
QUrl _link2_url;
|
||||||
|
|
||||||
|
public:
|
||||||
|
about_entry(QWidget* parent, ui::about::entry& entry);
|
||||||
|
~about_entry();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void on_link1_clicked();
|
||||||
|
void on_link2_clicked();
|
||||||
|
};
|
||||||
|
} // namespace streamfx::ui
|
||||||
|
|
@ -0,0 +1,204 @@
|
||||||
|
/*
|
||||||
|
* Modern effects for a modern Streamer
|
||||||
|
* Copyright (C) 2020 Michael Fabian Dirks
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ui-about.hpp"
|
||||||
|
#include <obs-frontend-api.h>
|
||||||
|
#include <map>
|
||||||
|
#include "ui-about-entry.hpp"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251 4365 4371 4619 4946)
|
||||||
|
#endif
|
||||||
|
#include <QLayout>
|
||||||
|
#include <QLayoutItem>
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
constexpr std::string_view text_social_facebook = "Facebook";
|
||||||
|
constexpr std::string_view text_social_twitch = "Twitch";
|
||||||
|
constexpr std::string_view text_social_twitter = "Twitter";
|
||||||
|
constexpr std::string_view text_social_youtube = "YouTube";
|
||||||
|
|
||||||
|
static const std::list<streamfx::ui::about::entry> _entries = {
|
||||||
|
// Contributers
|
||||||
|
streamfx::ui::about::entry{"Michael \"Xaymar\" Dirks", streamfx::ui::about::role_type::CONTRIBUTOR, "",
|
||||||
|
streamfx::ui::about::link_type::GENERIC, "https://xaymar.com", "Blog & Stuff",
|
||||||
|
streamfx::ui::about::link_type::SOCIAL_TWITCH, "https://twitch.tv/xaymar",
|
||||||
|
text_social_twitch.data()},
|
||||||
|
|
||||||
|
// Translators
|
||||||
|
streamfx::ui::about::entry{"FrozenNortherner", streamfx::ui::about::role_type::TRANSLATOR, "",
|
||||||
|
streamfx::ui::about::link_type::SOCIAL_TWITCH, "https://twitch.tv/frozennortherner",
|
||||||
|
text_social_twitch.data(), streamfx::ui::about::link_type::NONE, "", ""},
|
||||||
|
streamfx::ui::about::entry{"HANAWINS", streamfx::ui::about::role_type::TRANSLATOR, "",
|
||||||
|
streamfx::ui::about::link_type::SOCIAL_TWITCH, "https://www.twitch.tv/hanawins",
|
||||||
|
text_social_twitch.data(), streamfx::ui::about::link_type::NONE, "", ""},
|
||||||
|
streamfx::ui::about::entry{"hydargos", streamfx::ui::about::role_type::TRANSLATOR, "",
|
||||||
|
streamfx::ui::about::link_type::SOCIAL_TWITCH, "https://www.youtube.com/hydargos",
|
||||||
|
text_social_youtube.data(), streamfx::ui::about::link_type::NONE, "", ""},
|
||||||
|
streamfx::ui::about::entry{"Monsteer", streamfx::ui::about::role_type::TRANSLATOR, "",
|
||||||
|
streamfx::ui::about::link_type::SOCIAL_TWITTER, "https://twitter.com/cooliguay",
|
||||||
|
text_social_twitter.data(), streamfx::ui::about::link_type::NONE, "", ""},
|
||||||
|
streamfx::ui::about::entry{"Nanito", streamfx::ui::about::role_type::TRANSLATOR, "",
|
||||||
|
streamfx::ui::about::link_type::SOCIAL_TWITCH, "https://twitch.tv/nanito",
|
||||||
|
text_social_twitch.data(), streamfx::ui::about::link_type::SOCIAL_FACEBOOK,
|
||||||
|
"https://facebook.com/nanitotv", text_social_facebook.data()},
|
||||||
|
|
||||||
|
// Separator
|
||||||
|
streamfx::ui::about::entry{"", streamfx::ui::about::role_type::NONE, "", streamfx::ui::about::link_type::NONE, "",
|
||||||
|
"", streamfx::ui::about::link_type::NONE, "", ""},
|
||||||
|
|
||||||
|
// Supporters
|
||||||
|
streamfx::ui::about::entry{"GranDroidTonight", streamfx::ui::about::role_type::PATREON_SUPPORTER, "",
|
||||||
|
streamfx::ui::about::link_type::SOCIAL_TWITCH, "https://www.twitch.tv/GranDroidTonight",
|
||||||
|
text_social_twitch.data(), streamfx::ui::about::link_type::SOCIAL_YOUTUBE,
|
||||||
|
"https://youtube.com/channel/UCGoT2XFPpeKaL1QuY_NPDuA", text_social_youtube.data()},
|
||||||
|
streamfx::ui::about::entry{"chi11estpanda", streamfx::ui::about::role_type::PATREON_SUPPORTER, "",
|
||||||
|
streamfx::ui::about::link_type::SOCIAL_TWITCH, "https://www.twitch.tv/chi11estpanda",
|
||||||
|
"Gaming, Life and Laughs", streamfx::ui::about::link_type::NONE, "", ""},
|
||||||
|
streamfx::ui::about::entry{"DandiDoesIt", streamfx::ui::about::role_type::PATREON_SUPPORTER, "",
|
||||||
|
streamfx::ui::about::link_type::SOCIAL_TWITCH, "https://www.twitch.tv/DandiDoesIt",
|
||||||
|
"Twitch Channel", streamfx::ui::about::link_type::NONE, "", ""},
|
||||||
|
streamfx::ui::about::entry{"iamresist", streamfx::ui::about::role_type::PATREON_SUPPORTER, "",
|
||||||
|
streamfx::ui::about::link_type::SOCIAL_TWITCH, "https://twitch.tv/iamresist",
|
||||||
|
text_social_twitch.data(), streamfx::ui::about::link_type::NONE, "", ""},
|
||||||
|
streamfx::ui::about::entry{"Nordern", streamfx::ui::about::role_type::PATREON_SUPPORTER, "",
|
||||||
|
streamfx::ui::about::link_type::SOCIAL_YOUTUBE, "https://youtube.com/nordern",
|
||||||
|
text_social_youtube.data(), streamfx::ui::about::link_type::SOCIAL_TWITCH,
|
||||||
|
"https://www.twitch.tv/thenordern", text_social_twitch.data()},
|
||||||
|
|
||||||
|
// Separator
|
||||||
|
streamfx::ui::about::entry{"", streamfx::ui::about::role_type::NONE, "", streamfx::ui::about::link_type::NONE, "",
|
||||||
|
"", streamfx::ui::about::link_type::NONE, "", ""},
|
||||||
|
|
||||||
|
// Family
|
||||||
|
streamfx::ui::about::entry{"Andrea Stenschke", streamfx::ui::about::role_type::FAMILY, "Xaymar",
|
||||||
|
streamfx::ui::about::link_type::NONE, "", "", streamfx::ui::about::link_type::NONE, "",
|
||||||
|
""},
|
||||||
|
streamfx::ui::about::entry{"Carsten Dirks", streamfx::ui::about::role_type::FAMILY, "Xaymar",
|
||||||
|
streamfx::ui::about::link_type::NONE, "", "", streamfx::ui::about::link_type::NONE, "",
|
||||||
|
""},
|
||||||
|
streamfx::ui::about::entry{"Christian \"Azekil\" Dirks", streamfx::ui::about::role_type::FAMILY, "Xaymar",
|
||||||
|
streamfx::ui::about::link_type::NONE, "", "", streamfx::ui::about::link_type::NONE, "",
|
||||||
|
""},
|
||||||
|
streamfx::ui::about::entry{"Gabriele Rantfl", streamfx::ui::about::role_type::FAMILY, "Xaymar",
|
||||||
|
streamfx::ui::about::link_type::NONE, "", "", streamfx::ui::about::link_type::NONE, "",
|
||||||
|
""},
|
||||||
|
streamfx::ui::about::entry{"Reiner Rantfl", streamfx::ui::about::role_type::FAMILY, "Xaymar",
|
||||||
|
streamfx::ui::about::link_type::NONE, "", "", streamfx::ui::about::link_type::NONE, "",
|
||||||
|
""},
|
||||||
|
streamfx::ui::about::entry{"René \"Dex\" Dirks", streamfx::ui::about::role_type::FAMILY, "Xaymar",
|
||||||
|
streamfx::ui::about::link_type::SOCIAL_TWITCH, "https://twitch.tv/vektordex",
|
||||||
|
text_social_twitch.data(), streamfx::ui::about::link_type::GENERIC,
|
||||||
|
"https://worldofdex.de", "Website"},
|
||||||
|
|
||||||
|
// Friends
|
||||||
|
streamfx::ui::about::entry{"Axelle", streamfx::ui::about::role_type::FRIEND, "Xaymar",
|
||||||
|
streamfx::ui::about::link_type::SOCIAL_TWITCH, "https://www.twitch.tv/axelle123",
|
||||||
|
text_social_twitch.data(), streamfx::ui::about::link_type::SOCIAL_TWITTER,
|
||||||
|
"https://twitter.com/AxellesNobody", text_social_twitter.data()},
|
||||||
|
|
||||||
|
// Separator
|
||||||
|
streamfx::ui::about::entry{"", streamfx::ui::about::role_type::NONE, "", streamfx::ui::about::link_type::NONE, "",
|
||||||
|
"", streamfx::ui::about::link_type::NONE, "", ""},
|
||||||
|
|
||||||
|
// Creators
|
||||||
|
streamfx::ui::about::entry{"EposVox", streamfx::ui::about::role_type::CREATOR, "",
|
||||||
|
streamfx::ui::about::link_type::SOCIAL_TWITCH, "https://www.twitch.tv/EposVox",
|
||||||
|
text_social_twitch.data(), streamfx::ui::about::link_type::SOCIAL_YOUTUBE,
|
||||||
|
"https://youtube.com/c/EposVox", text_social_youtube.data()},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
streamfx::ui::about::about() : QDialog(reinterpret_cast<QWidget*>(obs_frontend_get_main_window()))
|
||||||
|
{
|
||||||
|
setupUi(this);
|
||||||
|
|
||||||
|
// Remove some extra styling.
|
||||||
|
setWindowFlag(Qt::WindowContextHelpButtonHint, false); // Remove the unimplemented help button.
|
||||||
|
|
||||||
|
// Thank every single helper.
|
||||||
|
bool column_selector = false;
|
||||||
|
size_t row_selector = 0;
|
||||||
|
QGridLayout* content_layout = dynamic_cast<QGridLayout*>(content->layout());
|
||||||
|
for (auto entry : _entries) {
|
||||||
|
if (entry.name.size() == 0) {
|
||||||
|
row_selector += 2;
|
||||||
|
column_selector = 0;
|
||||||
|
|
||||||
|
// Add a separator line.
|
||||||
|
auto separator = new QFrame(content);
|
||||||
|
{
|
||||||
|
auto sp = separator->sizePolicy();
|
||||||
|
sp.setVerticalPolicy(QSizePolicy::Fixed);
|
||||||
|
separator->setSizePolicy(sp);
|
||||||
|
}
|
||||||
|
separator->setFrameShape(QFrame::HLine);
|
||||||
|
separator->setFrameShadow(QFrame::Sunken);
|
||||||
|
separator->setMaximumHeight(1);
|
||||||
|
separator->setMinimumHeight(1);
|
||||||
|
separator->setFixedHeight(1);
|
||||||
|
separator->setLineWidth(1);
|
||||||
|
content_layout->addWidget(separator, static_cast<int>(row_selector - 1), 0, 1, 2);
|
||||||
|
content_layout->setRowStretch(static_cast<int>(row_selector - 1), 0);
|
||||||
|
} else {
|
||||||
|
streamfx::ui::about_entry* v = new streamfx::ui::about_entry(content, entry);
|
||||||
|
|
||||||
|
content_layout->addWidget(v, static_cast<int>(row_selector), column_selector ? 1 : 0);
|
||||||
|
content_layout->setRowStretch(static_cast<int>(row_selector), 0);
|
||||||
|
|
||||||
|
if (column_selector) {
|
||||||
|
row_selector++;
|
||||||
|
}
|
||||||
|
column_selector = !column_selector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
row_selector++;
|
||||||
|
auto padder = new QFrame(content);
|
||||||
|
{
|
||||||
|
auto sp = padder->sizePolicy();
|
||||||
|
sp.setVerticalPolicy(QSizePolicy::Minimum);
|
||||||
|
sp.setVerticalStretch(1);
|
||||||
|
padder->setSizePolicy(sp);
|
||||||
|
}
|
||||||
|
padder->setObjectName("PaddleMeDaddy");
|
||||||
|
padder->setMaximumHeight(QWIDGETSIZE_MAX);
|
||||||
|
padder->setMinimumHeight(1);
|
||||||
|
padder->setFrameShape(QFrame::NoFrame);
|
||||||
|
content_layout->addWidget(padder, static_cast<int>(row_selector), 0, 1, 2);
|
||||||
|
content_layout->setRowStretch(static_cast<int>(row_selector), 9999);
|
||||||
|
}
|
||||||
|
|
||||||
|
content_layout->setColumnStretch(0, 1);
|
||||||
|
content_layout->setColumnStretch(1, 1);
|
||||||
|
content->setSizePolicy(QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Maximum);
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* Modern effects for a modern Streamer
|
||||||
|
* Copyright (C) 2020 Michael Fabian Dirks
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "ui-common.hpp"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251 4365 4371 4619 4946)
|
||||||
|
#endif
|
||||||
|
#include "ui_about.h"
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace streamfx::ui {
|
||||||
|
class about : public QDialog, public Ui::About {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum class role_type : std::int32_t {
|
||||||
|
NONE,
|
||||||
|
CONTRIBUTOR,
|
||||||
|
TRANSLATOR,
|
||||||
|
FAMILY,
|
||||||
|
FRIEND,
|
||||||
|
PATREON_SUPPORTER,
|
||||||
|
GITHUB_SUPPORTER,
|
||||||
|
TWITCH_SUPPORTER,
|
||||||
|
CREATOR,
|
||||||
|
};
|
||||||
|
enum class link_type : std::int32_t {
|
||||||
|
NONE,
|
||||||
|
GENERIC,
|
||||||
|
|
||||||
|
// Social Links
|
||||||
|
SOCIAL_TWITCH = 2000,
|
||||||
|
SOCIAL_YOUTUBE,
|
||||||
|
SOCIAL_DISCORD,
|
||||||
|
SOCIAL_TWITTER,
|
||||||
|
SOCIAL_FACEBOOK,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct entry {
|
||||||
|
std::string name;
|
||||||
|
ui::about::role_type role;
|
||||||
|
std::string role_custom;
|
||||||
|
|
||||||
|
ui::about::link_type link1_type;
|
||||||
|
std::string link1_address;
|
||||||
|
std::string link1_text;
|
||||||
|
|
||||||
|
ui::about::link_type link2_type;
|
||||||
|
std::string link2_address;
|
||||||
|
std::string link2_text;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
about();
|
||||||
|
~about();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
; // Not having this breaks some linters.
|
||||||
|
void on_ok();
|
||||||
|
};
|
||||||
|
} // namespace streamfx::ui
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Modern effects for a modern Streamer
|
||||||
|
* Copyright (C) 2017 Michael Fabian Dirks
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4251 4365 4371 4619 4946)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QTranslator>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <obs-frontend-api.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,200 @@
|
||||||
|
/*
|
||||||
|
* Modern effects for a modern Streamer
|
||||||
|
* Copyright (C) 2020 Michael Fabian Dirks
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ui.hpp"
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "strings.hpp"
|
||||||
|
#include <string_view>
|
||||||
|
#include "configuration.hpp"
|
||||||
|
#include "obs/obs-tools.hpp"
|
||||||
|
#include "plugin.hpp"
|
||||||
|
|
||||||
|
#include <obs-frontend-api.h>
|
||||||
|
|
||||||
|
// Translation Keys
|
||||||
|
constexpr std::string_view _i18n_prefix = "StreamFX::";
|
||||||
|
constexpr std::string_view _i18n_menu = "UI.Menu";
|
||||||
|
constexpr std::string_view _i18n_menu_report_issue = "UI.Menu.ReportIssue";
|
||||||
|
constexpr std::string_view _i18n_menu_request_help = "UI.Menu.RequestHelp";
|
||||||
|
constexpr std::string_view _i18n_menu_website = "UI.Menu.Website";
|
||||||
|
constexpr std::string_view _i18n_menu_discord = "UI.Menu.Discord";
|
||||||
|
constexpr std::string_view _i18n_menu_github = "UI.Menu.Github";
|
||||||
|
constexpr std::string_view _i18n_menu_about = "UI.Menu.About";
|
||||||
|
|
||||||
|
// Configuration
|
||||||
|
constexpr std::string_view _cfg_have_shown_about = "UI.HaveShownAboutStreamFX";
|
||||||
|
|
||||||
|
// URLs
|
||||||
|
constexpr std::string_view _url_report_issue = "https://github.com/Xaymar/obs-StreamFX/issues/new?template=issue.md";
|
||||||
|
constexpr std::string_view _url_request_help = "https://github.com/Xaymar/obs-StreamFX/issues/new?template=help.md";
|
||||||
|
constexpr std::string_view _url_website = "https://streamfx.xaymar.com";
|
||||||
|
constexpr std::string_view _url_discord = "https://discordapp.com/invite/DaeJg7M";
|
||||||
|
constexpr std::string_view _url_github = "https://github.com/Xaymar/obs-StreamFX";
|
||||||
|
|
||||||
|
bool streamfx::ui::handler::have_shown_about_streamfx(bool shown)
|
||||||
|
{
|
||||||
|
if (shown) {
|
||||||
|
obs_data_set_bool(streamfx::configuration::instance()->get().get(), _cfg_have_shown_about.data(), true);
|
||||||
|
}
|
||||||
|
if (streamfx::configuration::instance()->is_different_version()) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return obs_data_get_bool(streamfx::configuration::instance()->get().get(), _cfg_have_shown_about.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
streamfx::ui::handler::handler()
|
||||||
|
: QObject(), _menu_action(), _menu(),
|
||||||
|
|
||||||
|
_report_issue(), _request_help(),
|
||||||
|
|
||||||
|
_link_website(), _link_discord(), _link_github(),
|
||||||
|
|
||||||
|
_about_action(), _about_dialog()
|
||||||
|
{
|
||||||
|
// Qt Resources and Translators
|
||||||
|
Q_INIT_RESOURCE(streamfx);
|
||||||
|
QCoreApplication::installTranslator(new streamfx::ui::translator(this));
|
||||||
|
|
||||||
|
// Handle all frontend events.
|
||||||
|
obs_frontend_add_event_callback(frontend_event_handler, this);
|
||||||
|
|
||||||
|
{ // Build StreamFX menu.
|
||||||
|
_menu = new QMenu(reinterpret_cast<QWidget*>(obs_frontend_get_main_window()));
|
||||||
|
|
||||||
|
{ // Github Issues
|
||||||
|
//_menu->addSeparator();
|
||||||
|
_report_issue = _menu->addAction(QString::fromUtf8(D_TRANSLATE(_i18n_menu_report_issue.data())));
|
||||||
|
_request_help = _menu->addAction(QString::fromUtf8(D_TRANSLATE(_i18n_menu_request_help.data())));
|
||||||
|
connect(_report_issue, &QAction::triggered, this, &streamfx::ui::handler::on_action_report_issue);
|
||||||
|
connect(_request_help, &QAction::triggered, this, &streamfx::ui::handler::on_action_request_help);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // Official Links
|
||||||
|
_menu->addSeparator();
|
||||||
|
_link_website = _menu->addAction(QString::fromUtf8(D_TRANSLATE(_i18n_menu_website.data())));
|
||||||
|
_link_discord = _menu->addAction(QString::fromUtf8(D_TRANSLATE(_i18n_menu_discord.data())));
|
||||||
|
_link_github = _menu->addAction(QString::fromUtf8(D_TRANSLATE(_i18n_menu_github.data())));
|
||||||
|
connect(_link_website, &QAction::triggered, this, &streamfx::ui::handler::on_action_website);
|
||||||
|
connect(_link_discord, &QAction::triggered, this, &streamfx::ui::handler::on_action_discord);
|
||||||
|
connect(_link_github, &QAction::triggered, this, &streamfx::ui::handler::on_action_github);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // About StreamFX
|
||||||
|
_about_dialog = new streamfx::ui::about();
|
||||||
|
_menu->addSeparator();
|
||||||
|
_about_action = _menu->addAction(QString::fromUtf8(D_TRANSLATE(_i18n_menu_about.data())));
|
||||||
|
connect(_about_action, &QAction::triggered, this, &streamfx::ui::handler::on_action_about);
|
||||||
|
if (!have_shown_about_streamfx()) {
|
||||||
|
// Automatically show it if it has not yet been shown.
|
||||||
|
_about_dialog->show();
|
||||||
|
have_shown_about_streamfx(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
streamfx::ui::handler::~handler()
|
||||||
|
{
|
||||||
|
// Handle all frontend events.
|
||||||
|
obs_frontend_remove_event_callback(frontend_event_handler, this);
|
||||||
|
|
||||||
|
// Qt Resources and Translators
|
||||||
|
Q_CLEANUP_RESOURCE(streamfx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void streamfx::ui::handler::frontend_event_handler(obs_frontend_event event, void* private_data)
|
||||||
|
{
|
||||||
|
streamfx::ui::handler* ptr = reinterpret_cast<streamfx::ui::handler*>(private_data);
|
||||||
|
switch (event) {
|
||||||
|
case OBS_FRONTEND_EVENT_FINISHED_LOADING:
|
||||||
|
ptr->on_obs_loaded();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void streamfx::ui::handler::on_obs_loaded()
|
||||||
|
{
|
||||||
|
// Add StreamFX menu.
|
||||||
|
_menu_action = reinterpret_cast<QAction*>(obs_frontend_add_tools_menu_qaction(D_TRANSLATE(_i18n_menu.data())));
|
||||||
|
_menu_action->setMenu(_menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
void streamfx::ui::handler::on_action_report_issue(bool)
|
||||||
|
{
|
||||||
|
QDesktopServices::openUrl(QUrl(QString::fromUtf8(_url_report_issue.data())));
|
||||||
|
}
|
||||||
|
|
||||||
|
void streamfx::ui::handler::on_action_request_help(bool)
|
||||||
|
{
|
||||||
|
QDesktopServices::openUrl(QUrl(QString::fromUtf8(_url_request_help.data())));
|
||||||
|
}
|
||||||
|
|
||||||
|
void streamfx::ui::handler::on_action_website(bool)
|
||||||
|
{
|
||||||
|
QDesktopServices::openUrl(QUrl(QString::fromUtf8(_url_website.data())));
|
||||||
|
}
|
||||||
|
|
||||||
|
void streamfx::ui::handler::on_action_discord(bool)
|
||||||
|
{
|
||||||
|
QDesktopServices::openUrl(QUrl(QString::fromUtf8(_url_discord.data())));
|
||||||
|
}
|
||||||
|
|
||||||
|
void streamfx::ui::handler::on_action_github(bool)
|
||||||
|
{
|
||||||
|
QDesktopServices::openUrl(QUrl(QString::fromUtf8(_url_github.data())));
|
||||||
|
}
|
||||||
|
|
||||||
|
void streamfx::ui::handler::on_action_about(bool checked)
|
||||||
|
{
|
||||||
|
_about_dialog->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::shared_ptr<streamfx::ui::handler> _handler_singleton;
|
||||||
|
|
||||||
|
void streamfx::ui::handler::initialize()
|
||||||
|
{
|
||||||
|
_handler_singleton = std::make_shared<streamfx::ui::handler>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void streamfx::ui::handler::finalize()
|
||||||
|
{
|
||||||
|
_handler_singleton.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<streamfx::ui::handler> streamfx::ui::handler::get()
|
||||||
|
{
|
||||||
|
return _handler_singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
streamfx::ui::translator::translator(QObject* parent) {}
|
||||||
|
|
||||||
|
streamfx::ui::translator::~translator() {}
|
||||||
|
|
||||||
|
QString streamfx::ui::translator::translate(const char* context, const char* sourceText, const char* disambiguation,
|
||||||
|
int n) const
|
||||||
|
{
|
||||||
|
std::string_view sourceView{sourceText};
|
||||||
|
if (sourceView.substr(0, _i18n_prefix.length()) == _i18n_prefix) {
|
||||||
|
return QString::fromUtf8(D_TRANSLATE(sourceView.substr(_i18n_prefix.length()).data()));
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* Modern effects for a modern Streamer
|
||||||
|
* Copyright (C) 2020 Michael Fabian Dirks
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "ui-about.hpp"
|
||||||
|
#include "ui-common.hpp"
|
||||||
|
|
||||||
|
namespace streamfx::ui {
|
||||||
|
class handler : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
QAction* _menu_action;
|
||||||
|
QMenu* _menu;
|
||||||
|
|
||||||
|
// Bug Report, Help Request
|
||||||
|
QAction* _report_issue;
|
||||||
|
QAction* _request_help;
|
||||||
|
|
||||||
|
// Website, Discord, Source
|
||||||
|
QAction* _link_website;
|
||||||
|
QAction* _link_discord;
|
||||||
|
QAction* _link_github;
|
||||||
|
|
||||||
|
// About Dialog
|
||||||
|
QAction* _about_action;
|
||||||
|
ui::about* _about_dialog;
|
||||||
|
|
||||||
|
public:
|
||||||
|
handler();
|
||||||
|
~handler();
|
||||||
|
|
||||||
|
bool have_shown_about_streamfx(bool shown = false);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void frontend_event_handler(obs_frontend_event event, void* private_data);
|
||||||
|
|
||||||
|
void on_obs_loaded();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
; // Not having this breaks some linters.
|
||||||
|
void on_action_report_issue(bool);
|
||||||
|
void on_action_request_help(bool);
|
||||||
|
void on_action_website(bool);
|
||||||
|
void on_action_discord(bool);
|
||||||
|
void on_action_github(bool);
|
||||||
|
void on_action_about(bool);
|
||||||
|
|
||||||
|
public /* Singleton */:
|
||||||
|
static void initialize();
|
||||||
|
|
||||||
|
static void finalize();
|
||||||
|
|
||||||
|
static std::shared_ptr<ui::handler> get();
|
||||||
|
};
|
||||||
|
|
||||||
|
class translator : public QTranslator {
|
||||||
|
public:
|
||||||
|
translator(QObject* parent = nullptr);
|
||||||
|
~translator();
|
||||||
|
|
||||||
|
virtual QString translate(const char* context, const char* sourceText, const char* disambiguation = nullptr,
|
||||||
|
int n = -1) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace streamfx::ui
|
||||||
|
|
@ -0,0 +1,243 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>AboutEntry</class>
|
||||||
|
<widget class="QWidget" name="AboutEntry">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>195</width>
|
||||||
|
<height>99</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QWidget {
|
||||||
|
background: hsl(0, 0%, 20%);
|
||||||
|
color: hsl(0, 0%, 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton,
|
||||||
|
QPushButton:default,
|
||||||
|
QPushButton:flat,
|
||||||
|
QPushButton:checked {
|
||||||
|
background: hsl(0, 0%, 25%);
|
||||||
|
border: 0;
|
||||||
|
padding: 5px;
|
||||||
|
box-shadow: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget[objectName="title"] {
|
||||||
|
color: hsl(200, 100%, 80%);
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="name">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Ignored" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>14</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
<stylestrategy>PreferAntialias</stylestrategy>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">Supporter Name</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="title">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">Supporter Title</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="linkLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="link1">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>36</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>36</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="baseSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>36</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">YouTube</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>:/social/youtube</normaloff>:/social/youtube</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="link2">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>36</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>36</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="baseSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>36</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>10</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">Twitch</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>:/social/twitch</normaloff>:/social/twitch</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources>
|
||||||
|
<include location="streamfx.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>About</class>
|
||||||
|
<widget class="QWidget" name="About">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>512</width>
|
||||||
|
<height>512</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>512</width>
|
||||||
|
<height>512</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>1024</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string comment="StreamFX::UI.About.Title">StreamFX::UI.About.Title</string>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QWidget {
|
||||||
|
background: transparent;
|
||||||
|
color: hsl(0, 0%, 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget[objectName="About"],
|
||||||
|
QWidget[objectName="contentContainer"],
|
||||||
|
QWidget[objectName="content"] {
|
||||||
|
background: hsl(0, 0%, 10%);
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget[objectName="PaddleMeDaddy"] {
|
||||||
|
background: hsl(0, 0%, 10%);
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="logo">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="streamfx.qrc">:/logos/streamfx_logo</pixmap>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="text">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<kerning>true</kerning>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string comment="StreamFX::UI.About.Text"><html><head/><body><p>StreamFX is made possible by all the supporters on <a href="https://patreon.com/Xaymar"><span style=" text-decoration: underline; color:#00aaff;">Patreon</span></a>, on <a href="https://github.com/sponsors/xaymar"><span style=" text-decoration: underline; color:#00aaff;">Github Sponsors</span></a>, and anyone donating through <a href="https://paypal.me/Xaymar"><span style=" text-decoration: underline; color:#00aaff;">PayPal</span></a>. Additional thanks go out to all the translators helping out with the localization on <a href="https://crowdin.com/project/obs-stream-effects"><span style=" text-decoration: underline; color:#00aaff;">Crowdin</span></a>. You all are amazing!</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="openExternalLinks">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QScrollArea" name="contentContainer">
|
||||||
|
<property name="horizontalScrollBarPolicy">
|
||||||
|
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||||
|
</property>
|
||||||
|
<property name="widgetResizable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="content">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>492</width>
|
||||||
|
<height>282</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="spacing">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
<property name="centerButtons">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources>
|
||||||
|
<include location="streamfx.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
|
After Width: | Height: | Size: 613 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 937 B |
|
After Width: | Height: | Size: 656 B |
|
After Width: | Height: | Size: 727 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
|
@ -0,0 +1,13 @@
|
||||||
|
<RCC>
|
||||||
|
<qresource prefix="logos">
|
||||||
|
<file alias="streamfx_logo">logo.png</file>
|
||||||
|
</qresource>
|
||||||
|
<qresource prefix="linktype">
|
||||||
|
<file alias="discord">linktype_discord.png</file>
|
||||||
|
<file alias="facebook">linktype_facebook.png</file>
|
||||||
|
<file alias="generic">linktype_generic.png</file>
|
||||||
|
<file alias="twitch">linktype_twitch.png</file>
|
||||||
|
<file alias="twitter">linktype_twitter.png</file>
|
||||||
|
<file alias="youtube">linktype_youtube.png</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
||||||