mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
Clean up font management
Default to b.userName instead of message->account() Made font updatable in the Settings dialog with a font dialog More work on subscription badge loading Known issues: - Font isn't updated in a split until a new message is written in that split - When font/font size is changed, old messages don't have their size updated causing weird layout of old messages
This commit is contained in:
parent
d2cbef9dff
commit
1ecc6ff612
6 changed files with 204 additions and 104 deletions
|
@ -1,63 +1,61 @@
|
||||||
#include "fontmanager.hpp"
|
#include "fontmanager.hpp"
|
||||||
|
|
||||||
#define DEFAULT_FONT "Arial"
|
#include <QDebug>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
FontManager FontManager::instance;
|
|
||||||
|
|
||||||
FontManager::FontManager()
|
FontManager::FontManager()
|
||||||
: _generation(0)
|
: currentFontFamily("/appearance/currentFontFamily", "Arial")
|
||||||
|
, currentFontSize("/appearance/currentFontSize", 14)
|
||||||
|
, currentFont(this->currentFontFamily.getValue().c_str(), currentFontSize.getValue())
|
||||||
{
|
{
|
||||||
_medium = new QFont(DEFAULT_FONT, 14);
|
this->currentFontFamily.valueChanged.connect([this](const std::string &newValue) {
|
||||||
_mediumBold = new QFont(DEFAULT_FONT, 14);
|
this->currentFont.setFamily(newValue.c_str()); //
|
||||||
_mediumItalic = new QFont(DEFAULT_FONT, 14);
|
});
|
||||||
_small = new QFont(DEFAULT_FONT, 10);
|
this->currentFontSize.valueChanged.connect([this](const int &newValue) {
|
||||||
_large = new QFont(DEFAULT_FONT, 16);
|
this->currentFont.setSize(newValue); //
|
||||||
_veryLarge = new QFont(DEFAULT_FONT, 18);
|
});
|
||||||
|
|
||||||
_metricsMedium = new QFontMetrics(*_medium);
|
|
||||||
_metricsMediumBold = new QFontMetrics(*_mediumBold);
|
|
||||||
_metricsMediumItalic = new QFontMetrics(*_mediumItalic);
|
|
||||||
_metricsSmall = new QFontMetrics(*_small);
|
|
||||||
_metricsLarge = new QFontMetrics(*_large);
|
|
||||||
_metricsVeryLarge = new QFontMetrics(*_veryLarge);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QFont &FontManager::getFont(Type type)
|
QFont &FontManager::getFont(Type type)
|
||||||
{
|
{
|
||||||
if (type == Medium)
|
return this->currentFont.getFont(type);
|
||||||
return *_medium;
|
|
||||||
if (type == MediumBold)
|
|
||||||
return *_mediumBold;
|
|
||||||
if (type == MediumItalic)
|
|
||||||
return *_mediumItalic;
|
|
||||||
if (type == Small)
|
|
||||||
return *_small;
|
|
||||||
if (type == Large)
|
|
||||||
return *_large;
|
|
||||||
if (type == VeryLarge)
|
|
||||||
return *_veryLarge;
|
|
||||||
|
|
||||||
return *_medium;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QFontMetrics &FontManager::getFontMetrics(Type type)
|
QFontMetrics &FontManager::getFontMetrics(Type type)
|
||||||
{
|
{
|
||||||
if (type == Medium)
|
return this->currentFont.getFontMetrics(type);
|
||||||
return *_metricsMedium;
|
}
|
||||||
if (type == MediumBold)
|
|
||||||
return *_metricsMediumBold;
|
|
||||||
if (type == MediumItalic)
|
|
||||||
return *_metricsMediumItalic;
|
|
||||||
if (type == Small)
|
|
||||||
return *_metricsSmall;
|
|
||||||
if (type == Large)
|
|
||||||
return *_metricsLarge;
|
|
||||||
if (type == VeryLarge)
|
|
||||||
return *_metricsVeryLarge;
|
|
||||||
|
|
||||||
return *_metricsMedium;
|
FontManager::FontData &FontManager::Font::getFontData(Type type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case Small:
|
||||||
|
return this->small;
|
||||||
|
case Medium:
|
||||||
|
return this->medium;
|
||||||
|
case MediumBold:
|
||||||
|
return this->mediumBold;
|
||||||
|
case MediumItalic:
|
||||||
|
return this->mediumItalic;
|
||||||
|
case Large:
|
||||||
|
return this->large;
|
||||||
|
case VeryLarge:
|
||||||
|
return this->veryLarge;
|
||||||
|
default:
|
||||||
|
qDebug() << "Unknown font type:" << type << ", defaulting to medium";
|
||||||
|
return this->medium;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QFont &FontManager::Font::getFont(Type type)
|
||||||
|
{
|
||||||
|
return this->getFontData(type).font;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFontMetrics &FontManager::Font::getFontMetrics(Type type)
|
||||||
|
{
|
||||||
|
return this->getFontData(type).metrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -2,52 +2,126 @@
|
||||||
|
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include <QFontMetrics>
|
#include <QFontMetrics>
|
||||||
|
#include <pajlada/settings/setting.hpp>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class FontManager
|
class FontManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Type : char { Medium, MediumBold, MediumItalic, Small, Large, VeryLarge };
|
enum Type : uint8_t {
|
||||||
|
Small,
|
||||||
|
Medium,
|
||||||
|
MediumBold,
|
||||||
|
MediumItalic,
|
||||||
|
Large,
|
||||||
|
VeryLarge,
|
||||||
|
};
|
||||||
|
|
||||||
|
// FontManager is initialized only once, on first use
|
||||||
static FontManager &getInstance()
|
static FontManager &getInstance()
|
||||||
{
|
{
|
||||||
|
static FontManager instance;
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
QFont &getFont(Type type);
|
QFont &getFont(Type type);
|
||||||
QFontMetrics &getFontMetrics(Type type);
|
QFontMetrics &getFontMetrics(Type type);
|
||||||
|
|
||||||
int getGeneration()
|
int getGeneration() const
|
||||||
{
|
{
|
||||||
return _generation;
|
return this->generation;
|
||||||
}
|
}
|
||||||
|
|
||||||
void incGeneration()
|
void incGeneration()
|
||||||
{
|
{
|
||||||
_generation++;
|
this->generation++;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
pajlada::Settings::Setting<std::string> currentFontFamily;
|
||||||
static FontManager instance;
|
pajlada::Settings::Setting<int> currentFontSize;
|
||||||
|
|
||||||
|
private:
|
||||||
FontManager();
|
FontManager();
|
||||||
|
|
||||||
QFont *_medium;
|
struct FontData {
|
||||||
QFont *_mediumBold;
|
FontData(QFont &&_font)
|
||||||
QFont *_mediumItalic;
|
: font(_font)
|
||||||
QFont *_small;
|
, metrics(this->font)
|
||||||
QFont *_large;
|
{
|
||||||
QFont *_veryLarge;
|
}
|
||||||
|
|
||||||
QFontMetrics *_metricsMedium;
|
QFont font;
|
||||||
QFontMetrics *_metricsMediumBold;
|
QFontMetrics metrics;
|
||||||
QFontMetrics *_metricsMediumItalic;
|
};
|
||||||
QFontMetrics *_metricsSmall;
|
|
||||||
QFontMetrics *_metricsLarge;
|
|
||||||
QFontMetrics *_metricsVeryLarge;
|
|
||||||
|
|
||||||
int _generation;
|
struct Font {
|
||||||
|
Font() = delete;
|
||||||
|
|
||||||
|
explicit Font(const char *fontFamilyName, int mediumSize)
|
||||||
|
: small(QFont(fontFamilyName, mediumSize - 4))
|
||||||
|
, medium(QFont(fontFamilyName, mediumSize))
|
||||||
|
, mediumBold(QFont(fontFamilyName, mediumSize, 50))
|
||||||
|
, mediumItalic(QFont(fontFamilyName, mediumSize, -1, true))
|
||||||
|
, large(QFont(fontFamilyName, mediumSize))
|
||||||
|
, veryLarge(QFont(fontFamilyName, mediumSize))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFamily(const char *newFamily)
|
||||||
|
{
|
||||||
|
this->small.font.setFamily(newFamily);
|
||||||
|
this->medium.font.setFamily(newFamily);
|
||||||
|
this->mediumBold.font.setFamily(newFamily);
|
||||||
|
this->mediumItalic.font.setFamily(newFamily);
|
||||||
|
this->large.font.setFamily(newFamily);
|
||||||
|
this->veryLarge.font.setFamily(newFamily);
|
||||||
|
|
||||||
|
this->updateMetrics();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSize(int newMediumSize)
|
||||||
|
{
|
||||||
|
this->small.font.setPointSize(newMediumSize - 4);
|
||||||
|
this->medium.font.setPointSize(newMediumSize);
|
||||||
|
this->mediumBold.font.setPointSize(newMediumSize);
|
||||||
|
this->mediumItalic.font.setPointSize(newMediumSize);
|
||||||
|
this->large.font.setPointSize(newMediumSize + 2);
|
||||||
|
this->veryLarge.font.setPointSize(newMediumSize + 4);
|
||||||
|
|
||||||
|
this->updateMetrics();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateMetrics()
|
||||||
|
{
|
||||||
|
this->small.metrics = QFontMetrics(this->small.font);
|
||||||
|
this->medium.metrics = QFontMetrics(this->medium.font);
|
||||||
|
this->mediumBold.metrics = QFontMetrics(this->mediumBold.font);
|
||||||
|
this->mediumItalic.metrics = QFontMetrics(this->mediumItalic.font);
|
||||||
|
this->large.metrics = QFontMetrics(this->large.font);
|
||||||
|
this->veryLarge.metrics = QFontMetrics(this->veryLarge.font);
|
||||||
|
}
|
||||||
|
|
||||||
|
FontData &getFontData(Type type);
|
||||||
|
|
||||||
|
QFont &getFont(Type type);
|
||||||
|
QFontMetrics &getFontMetrics(Type type);
|
||||||
|
|
||||||
|
FontData small;
|
||||||
|
FontData medium;
|
||||||
|
FontData mediumBold;
|
||||||
|
FontData mediumItalic;
|
||||||
|
FontData large;
|
||||||
|
FontData veryLarge;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Future plans:
|
||||||
|
// Could have multiple fonts in here, such as "Menu font", "Application font", "Chat font"
|
||||||
|
|
||||||
|
Font currentFont;
|
||||||
|
|
||||||
|
int generation = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -18,27 +18,29 @@ inline messages::LazyLoadedImage *lli(EmoteManager &emoteManager, WindowManager
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Resources::Resources(EmoteManager &emoteManager, WindowManager &windowManager)
|
Resources::Resources(EmoteManager &em, WindowManager &wm)
|
||||||
: badgeStaff(lli(emoteManager, windowManager, ":/images/staff_bg.png"))
|
: emoteManager(em)
|
||||||
, badgeAdmin(lli(emoteManager, windowManager, ":/images/admin_bg.png"))
|
, windowManager(wm)
|
||||||
, badgeGlobalModerator(lli(emoteManager, windowManager, ":/images/globalmod_bg.png"))
|
, badgeStaff(lli(em, wm, ":/images/staff_bg.png"))
|
||||||
, badgeModerator(lli(emoteManager, windowManager, ":/images/moderator_bg.png"))
|
, badgeAdmin(lli(em, wm, ":/images/admin_bg.png"))
|
||||||
, badgeTurbo(lli(emoteManager, windowManager, ":/images/turbo_bg.png"))
|
, badgeGlobalModerator(lli(em, wm, ":/images/globalmod_bg.png"))
|
||||||
, badgeBroadcaster(lli(emoteManager, windowManager, ":/images/broadcaster_bg.png"))
|
, badgeModerator(lli(em, wm, ":/images/moderator_bg.png"))
|
||||||
, badgePremium(lli(emoteManager, windowManager, ":/images/twitchprime_bg.png"))
|
, badgeTurbo(lli(em, wm, ":/images/turbo_bg.png"))
|
||||||
, badgeVerified(lli(emoteManager, windowManager, ":/images/verified.png", 0.25))
|
, badgeBroadcaster(lli(em, wm, ":/images/broadcaster_bg.png"))
|
||||||
, cheerBadge100000(lli(emoteManager, windowManager, ":/images/cheer100000"))
|
, badgePremium(lli(em, wm, ":/images/twitchprime_bg.png"))
|
||||||
, cheerBadge10000(lli(emoteManager, windowManager, ":/images/cheer10000"))
|
, badgeVerified(lli(em, wm, ":/images/verified.png", 0.25))
|
||||||
, cheerBadge5000(lli(emoteManager, windowManager, ":/images/cheer5000"))
|
, cheerBadge100000(lli(em, wm, ":/images/cheer100000"))
|
||||||
, cheerBadge1000(lli(emoteManager, windowManager, ":/images/cheer1000"))
|
, cheerBadge10000(lli(em, wm, ":/images/cheer10000"))
|
||||||
, cheerBadge100(lli(emoteManager, windowManager, ":/images/cheer100"))
|
, cheerBadge5000(lli(em, wm, ":/images/cheer5000"))
|
||||||
, cheerBadge1(lli(emoteManager, windowManager, ":/images/cheer1"))
|
, cheerBadge1000(lli(em, wm, ":/images/cheer1000"))
|
||||||
, buttonBan(lli(emoteManager, windowManager, ":/images/button_ban.png", 0.25))
|
, cheerBadge100(lli(em, wm, ":/images/cheer100"))
|
||||||
, buttonTimeout(lli(emoteManager, windowManager, ":/images/button_timeout.png", 0.25))
|
, cheerBadge1(lli(em, wm, ":/images/cheer1"))
|
||||||
|
, buttonBan(lli(em, wm, ":/images/button_ban.png", 0.25))
|
||||||
|
, buttonTimeout(lli(em, wm, ":/images/button_timeout.png", 0.25))
|
||||||
{
|
{
|
||||||
QString badgesUrl("https://badges.twitch.tv/v1/badges/global/display?language=en");
|
QString badgesUrl("https://badges.twitch.tv/v1/badges/global/display?language=en");
|
||||||
|
|
||||||
util::urlJsonFetch(badgesUrl, [this, &emoteManager, &windowManager](QJsonObject &root) {
|
util::urlJsonFetch(badgesUrl, [this](QJsonObject &root) {
|
||||||
QJsonObject sets = root.value("badge_sets").toObject();
|
QJsonObject sets = root.value("badge_sets").toObject();
|
||||||
|
|
||||||
for (QJsonObject::iterator it = sets.begin(); it != sets.end(); ++it) {
|
for (QJsonObject::iterator it = sets.begin(); it != sets.end(); ++it) {
|
||||||
|
@ -51,7 +53,7 @@ Resources::Resources(EmoteManager &emoteManager, WindowManager &windowManager)
|
||||||
++versionIt) {
|
++versionIt) {
|
||||||
std::string kkey = versionIt.key().toStdString();
|
std::string kkey = versionIt.key().toStdString();
|
||||||
QJsonObject versionObj = versionIt.value().toObject();
|
QJsonObject versionObj = versionIt.value().toObject();
|
||||||
BadgeVersion v(std::move(versionObj), emoteManager, windowManager);
|
BadgeVersion v(std::move(versionObj), this->emoteManager, this->windowManager);
|
||||||
versionsMap.emplace(kkey, v);
|
versionsMap.emplace(kkey, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,24 +77,35 @@ Resources::BadgeVersion::BadgeVersion(QJsonObject &&root, EmoteManager &emoteMan
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resources::Channel::loadData()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
if (this->loaded) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->loaded = true;
|
|
||||||
|
|
||||||
if (this->id.empty()) {
|
|
||||||
//util::urlJsonFetch()
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void Resources::loadChannelData(const std::string &roomID, bool bypassCache)
|
void Resources::loadChannelData(const std::string &roomID, bool bypassCache)
|
||||||
{
|
{
|
||||||
qDebug() << "Load channel data for" << QString::fromStdString(roomID);
|
qDebug() << "Load channel data for" << QString::fromStdString(roomID);
|
||||||
|
|
||||||
|
// Step 1: Get
|
||||||
|
|
||||||
|
QString url = "https://badges.twitch.tv/v1/badges/channels/" + QString::fromStdString(roomID) +
|
||||||
|
"/display?language=en";
|
||||||
|
|
||||||
|
util::urlJsonFetch(url, [this](QJsonObject &root) {
|
||||||
|
QJsonObject sets = root.value("badge_sets").toObject();
|
||||||
|
|
||||||
|
for (QJsonObject::iterator it = sets.begin(); it != sets.end(); ++it) {
|
||||||
|
QJsonObject versions = it.value().toObject().value("versions").toObject();
|
||||||
|
|
||||||
|
auto &badgeSet = this->badgeSets[it.key().toStdString()];
|
||||||
|
auto &versionsMap = badgeSet.versions;
|
||||||
|
|
||||||
|
for (auto versionIt = std::begin(versions); versionIt != std::end(versions);
|
||||||
|
++versionIt) {
|
||||||
|
std::string kkey = versionIt.key().toStdString();
|
||||||
|
QJsonObject versionObj = versionIt.value().toObject();
|
||||||
|
BadgeVersion v(std::move(versionObj), this->emoteManager, this->windowManager);
|
||||||
|
versionsMap.emplace(kkey, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->dynamicBadgesLoaded = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -12,6 +12,9 @@ class WindowManager;
|
||||||
|
|
||||||
class Resources
|
class Resources
|
||||||
{
|
{
|
||||||
|
EmoteManager &emoteManager;
|
||||||
|
WindowManager &windowManager;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Resources(EmoteManager &emoteManager, WindowManager &windowManager);
|
explicit Resources(EmoteManager &emoteManager, WindowManager &windowManager);
|
||||||
|
|
||||||
|
@ -60,13 +63,9 @@ public:
|
||||||
messages::LazyLoadedImage *buttonTimeout;
|
messages::LazyLoadedImage *buttonTimeout;
|
||||||
|
|
||||||
struct Channel {
|
struct Channel {
|
||||||
std::string id;
|
std::map<std::string, BadgeSet> badgeSets;
|
||||||
|
|
||||||
std::mutex globalMapMutex;
|
bool loaded = false;
|
||||||
|
|
||||||
void loadData();
|
|
||||||
|
|
||||||
// std::atomic<bool> loaded = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// channelId
|
// channelId
|
||||||
|
|
|
@ -95,7 +95,7 @@ SharedMessage TwitchMessageBuilder::parse(const Communi::IrcPrivateMessage *ircM
|
||||||
|
|
||||||
iterator = tags.find("display-name");
|
iterator = tags.find("display-name");
|
||||||
if (iterator == tags.end()) {
|
if (iterator == tags.end()) {
|
||||||
displayName = ircMessage->account();
|
displayName = b.userName;
|
||||||
} else {
|
} else {
|
||||||
displayName = iterator.value().toString();
|
displayName = iterator.value().toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QFontDialog>
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
@ -108,7 +109,22 @@ void SettingsDialog::addTabs()
|
||||||
auto form = new QFormLayout();
|
auto form = new QFormLayout();
|
||||||
auto combo = new QComboBox();
|
auto combo = new QComboBox();
|
||||||
auto slider = new QSlider(Qt::Horizontal);
|
auto slider = new QSlider(Qt::Horizontal);
|
||||||
|
|
||||||
auto font = new QPushButton("select");
|
auto font = new QPushButton("select");
|
||||||
|
font->connect(font, &QPushButton::clicked, []() {
|
||||||
|
auto fontManager = FontManager::getInstance();
|
||||||
|
QFontDialog dialog(fontManager.getFont(FontManager::Medium));
|
||||||
|
|
||||||
|
dialog.connect(&dialog, &QFontDialog::fontSelected, [&dialog](const QFont &font) {
|
||||||
|
auto fontManager = FontManager::getInstance();
|
||||||
|
fontManager.currentFontFamily = font.family().toStdString();
|
||||||
|
fontManager.currentFontSize = font.pointSize();
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
|
dialog.exec();
|
||||||
|
});
|
||||||
|
|
||||||
auto compactTabs = createCheckbox("Hide tab X", settings.hideTabX);
|
auto compactTabs = createCheckbox("Hide tab X", settings.hideTabX);
|
||||||
auto hidePreferencesButton = createCheckbox("Hide preferences button (ctrl+p to show)",
|
auto hidePreferencesButton = createCheckbox("Hide preferences button (ctrl+p to show)",
|
||||||
settings.hidePreferencesButton);
|
settings.hidePreferencesButton);
|
||||||
|
|
Loading…
Reference in a new issue