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
|
||||
if(HAVE_OBS_FRONTEND)
|
||||
list(APPEND PROJECT_UI
|
||||
"ui/streamfx.qrc"
|
||||
"ui/about.ui"
|
||||
"ui/about-entry.ui"
|
||||
)
|
||||
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
|
||||
"source/ui"
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "plugin.hpp"
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include "configuration.hpp"
|
||||
#include "obs/obs-source-tracker.hpp"
|
||||
|
@ -62,6 +63,10 @@
|
|||
#include "transitions/transition-shader.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_FRONTEND
|
||||
#include "ui/ui.hpp"
|
||||
#endif
|
||||
|
||||
static std::shared_ptr<util::threadpool> _threadpool;
|
||||
|
||||
MODULE_EXPORT bool obs_module_load(void)
|
||||
|
@ -133,6 +138,11 @@ try {
|
|||
#endif
|
||||
}
|
||||
|
||||
// Frontend
|
||||
#ifdef ENABLE_FRONTEND
|
||||
streamfx::ui::handler::initialize();
|
||||
#endif
|
||||
|
||||
LOG_INFO("Loaded Version %s", STREAMFX_VERSION_STRING);
|
||||
return true;
|
||||
} catch (...) {
|
||||
|
@ -144,6 +154,11 @@ MODULE_EXPORT void obs_module_unload(void)
|
|||
try {
|
||||
LOG_INFO("Unloading Version %s", STREAMFX_VERSION_STRING);
|
||||
|
||||
// Frontend
|
||||
#ifdef ENABLE_FRONTEND
|
||||
streamfx::ui::handler::finalize();
|
||||
#endif
|
||||
|
||||
// Transitions
|
||||
{
|
||||
using namespace streamfx::transition;
|
||||
|
|
130
source/ui/ui-about-entry.cpp
Normal file
|
@ -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++) {
|
||||
}
|
||||
}
|
51
source/ui/ui-about-entry.hpp
Normal file
|
@ -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
|
204
source/ui/ui-about.cpp
Normal file
|
@ -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();
|
||||
}
|
83
source/ui/ui-about.hpp
Normal file
|
@ -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
|
43
source/ui/ui-common.hpp
Normal file
|
@ -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
|
200
source/ui/ui.cpp
Normal file
|
@ -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();
|
||||
}
|
82
source/ui/ui.hpp
Normal file
|
@ -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
|
243
ui/about-entry.ui
Normal file
|
@ -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>
|
173
ui/about.ui
Normal file
|
@ -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>
|
BIN
ui/linktype_discord.png
Normal file
After Width: | Height: | Size: 613 B |
BIN
ui/linktype_facebook.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
ui/linktype_generic.png
Normal file
After Width: | Height: | Size: 937 B |
BIN
ui/linktype_twitch.png
Normal file
After Width: | Height: | Size: 656 B |
BIN
ui/linktype_twitter.png
Normal file
After Width: | Height: | Size: 727 B |
BIN
ui/linktype_youtube.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
ui/logo.png
Normal file
After Width: | Height: | Size: 58 KiB |
13
ui/streamfx.qrc
Normal file
|
@ -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>
|