Merge branch 'master' into git_is_pepega
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
#include "Args.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
Args::Args(const QStringList &args)
|
||||
{
|
||||
for (auto &&arg : args)
|
||||
{
|
||||
if (arg == "--crash-recovery")
|
||||
{
|
||||
this->crashRecovery = true;
|
||||
}
|
||||
else if (arg == "--version")
|
||||
{
|
||||
this->printVersion = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Args *instance = nullptr;
|
||||
|
||||
void initArgs(const QStringList &args)
|
||||
{
|
||||
instance = new Args(args);
|
||||
}
|
||||
|
||||
const Args &getArgs()
|
||||
{
|
||||
assert(instance);
|
||||
|
||||
return *instance;
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
/// Command line arguments passed to Chatterino.
|
||||
class Args
|
||||
{
|
||||
public:
|
||||
Args(const QStringList &args);
|
||||
|
||||
bool printVersion{};
|
||||
bool crashRecovery{};
|
||||
};
|
||||
|
||||
void initArgs(const QStringList &args);
|
||||
const Args &getArgs();
|
||||
|
||||
} // namespace chatterino
|
||||
@@ -178,7 +178,7 @@ void Channel::addOrReplaceTimeout(MessagePtr message)
|
||||
}
|
||||
|
||||
// XXX: Might need the following line
|
||||
// WindowManager::getInstance().repaintVisibleChatWidgets(this);
|
||||
// WindowManager::instance().repaintVisibleChatWidgets(this);
|
||||
}
|
||||
|
||||
void Channel::disableAllMessages()
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "common/ChatterinoSetting.hpp"
|
||||
|
||||
#include "BaseSettings.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
void _registerSetting(std::weak_ptr<pajlada::Settings::SettingData> setting)
|
||||
{
|
||||
_actuallyRegisterSetting(setting);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
@@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <pajlada/settings.hpp>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
void _registerSetting(std::weak_ptr<pajlada::Settings::SettingData> setting);
|
||||
|
||||
template <typename Type>
|
||||
class ChatterinoSetting : public pajlada::Settings::Setting<Type>
|
||||
{
|
||||
public:
|
||||
ChatterinoSetting(const std::string &path)
|
||||
: pajlada::Settings::Setting<Type>(path)
|
||||
{
|
||||
_registerSetting(this->getData());
|
||||
}
|
||||
|
||||
ChatterinoSetting(const std::string &path, const Type &defaultValue)
|
||||
: pajlada::Settings::Setting<Type>(path, defaultValue)
|
||||
{
|
||||
_registerSetting(this->getData());
|
||||
}
|
||||
|
||||
template <typename T2>
|
||||
ChatterinoSetting &operator=(const T2 &newValue)
|
||||
{
|
||||
this->setValue(newValue);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ChatterinoSetting &operator=(Type &&newValue) noexcept
|
||||
{
|
||||
pajlada::Settings::Setting<Type>::operator=(newValue);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
using pajlada::Settings::Setting<Type>::operator==;
|
||||
using pajlada::Settings::Setting<Type>::operator!=;
|
||||
|
||||
using pajlada::Settings::Setting<Type>::operator Type;
|
||||
};
|
||||
|
||||
using BoolSetting = ChatterinoSetting<bool>;
|
||||
using FloatSetting = ChatterinoSetting<float>;
|
||||
using DoubleSetting = ChatterinoSetting<double>;
|
||||
using IntSetting = ChatterinoSetting<int>;
|
||||
using StringSetting = ChatterinoSetting<std::string>;
|
||||
using QStringSetting = ChatterinoSetting<QString>;
|
||||
|
||||
template <typename Enum>
|
||||
class EnumSetting
|
||||
: public ChatterinoSetting<typename std::underlying_type<Enum>::type>
|
||||
{
|
||||
using Underlying = typename std::underlying_type<Enum>::type;
|
||||
|
||||
public:
|
||||
using ChatterinoSetting<Underlying>::ChatterinoSetting;
|
||||
|
||||
EnumSetting(const std::string &path, const Enum &defaultValue)
|
||||
: ChatterinoSetting<Underlying>(path, Underlying(defaultValue))
|
||||
{
|
||||
_registerSetting(this->getData());
|
||||
}
|
||||
|
||||
template <typename T2>
|
||||
EnumSetting<Enum> &operator=(Enum newValue)
|
||||
{
|
||||
this->setValue(Underlying(newValue));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator Enum()
|
||||
{
|
||||
return Enum(this->getValue());
|
||||
}
|
||||
|
||||
Enum getEnum()
|
||||
{
|
||||
return Enum(this->getValue());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
+14
-5
@@ -1,16 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/Aliases.hpp"
|
||||
#include "common/Outcome.hpp"
|
||||
#include "common/ProviderId.hpp"
|
||||
|
||||
#include <QString>
|
||||
#include <QWidget>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/preprocessor.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common/Aliases.hpp"
|
||||
#include "common/Outcome.hpp"
|
||||
#include "common/ProviderId.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
enum class HighlightState {
|
||||
@@ -46,4 +45,14 @@ enum class CopyMode {
|
||||
OnlyTextAndEmotes,
|
||||
};
|
||||
|
||||
struct DeleteLater {
|
||||
void operator()(QObject *obj)
|
||||
{
|
||||
obj->deleteLater();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using QObjectPtr = std::unique_ptr<T, DeleteLater>;
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Credentials &Credentials::getInstance()
|
||||
Credentials &Credentials::instance()
|
||||
{
|
||||
static Credentials creds;
|
||||
return creds;
|
||||
@@ -166,11 +166,12 @@ void Credentials::get(const QString &provider, const QString &name_,
|
||||
auto job = new QKeychain::ReadPasswordJob("chatterino");
|
||||
job->setAutoDelete(true);
|
||||
job->setKey(name);
|
||||
QObject::connect(job, &QKeychain::Job::finished, receiver,
|
||||
[job, onLoaded = std::move(onLoaded)](auto) mutable {
|
||||
onLoaded(job->textData());
|
||||
},
|
||||
Qt::DirectConnection);
|
||||
QObject::connect(
|
||||
job, &QKeychain::Job::finished, receiver,
|
||||
[job, onLoaded = std::move(onLoaded)](auto) mutable {
|
||||
onLoaded(job->textData());
|
||||
},
|
||||
Qt::DirectConnection);
|
||||
job->start();
|
||||
}
|
||||
else
|
||||
@@ -199,7 +200,9 @@ void Credentials::set(const QString &provider, const QString &name_,
|
||||
{
|
||||
auto &instance = insecureInstance();
|
||||
|
||||
instance.object()[name] = credential;
|
||||
auto obj = instance.object();
|
||||
obj[name] = credential;
|
||||
instance.setObject(obj);
|
||||
|
||||
queueInsecureSave();
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace chatterino {
|
||||
class Credentials
|
||||
{
|
||||
public:
|
||||
static Credentials &getInstance();
|
||||
static Credentials &instance();
|
||||
|
||||
void get(const QString &provider, const QString &name, QObject *receiver,
|
||||
std::function<void(const QString &)> &&onLoaded);
|
||||
|
||||
@@ -48,13 +48,11 @@ void DownloadManager::onFinished(QNetworkReply *reply)
|
||||
{
|
||||
switch (reply->error())
|
||||
{
|
||||
case QNetworkReply::NoError:
|
||||
{
|
||||
case QNetworkReply::NoError: {
|
||||
qDebug("file is downloaded successfully.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
default: {
|
||||
qDebug() << reply->errorString().toLatin1();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "common/Env.hpp"
|
||||
|
||||
#include <QVariant>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
namespace {
|
||||
@@ -15,6 +17,33 @@ namespace {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
uint16_t readPortEnv(const char *envName, uint16_t defaultValue)
|
||||
{
|
||||
auto envString = std::getenv(envName);
|
||||
if (envString != nullptr)
|
||||
{
|
||||
bool ok;
|
||||
auto val = QString(envString).toUShort(&ok);
|
||||
if (ok)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
uint16_t readBoolEnv(const char *envName, bool defaultValue)
|
||||
{
|
||||
auto envString = std::getenv(envName);
|
||||
if (envString != nullptr)
|
||||
{
|
||||
return QVariant(QString(envString)).toBool();
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Env::Env()
|
||||
@@ -30,6 +59,10 @@ Env::Env()
|
||||
"https://braize.pajlada.com/chatterino/twitchemotes/set/%1/"))
|
||||
, imageUploaderUrl(readStringEnv("CHATTERINO2_IMAGE_PASTE_SITE_URL",
|
||||
"https://i.nuuls.com/upload"))
|
||||
, twitchServerHost(
|
||||
readStringEnv("CHATTERINO2_TWITCH_SERVER_HOST", "irc.chat.twitch.tv"))
|
||||
, twitchServerPort(readPortEnv("CHATTERINO2_TWITCH_SERVER_PORT", 6697))
|
||||
, twitchServerSecure(readBoolEnv("CHATTERINO2_TWITCH_SERVER_SECURE", true))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@ public:
|
||||
const QString linkResolverUrl;
|
||||
const QString twitchEmoteSetResolverUrl;
|
||||
const QString imageUploaderUrl;
|
||||
const QString twitchServerHost;
|
||||
const uint16_t twitchServerPort;
|
||||
const bool twitchServerSecure;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
template <typename T, typename Q = typename std::underlying_type<T>::type>
|
||||
class FlagsEnum
|
||||
{
|
||||
public:
|
||||
FlagsEnum()
|
||||
: value_(static_cast<T>(0))
|
||||
{
|
||||
}
|
||||
|
||||
FlagsEnum(T value)
|
||||
: value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
FlagsEnum(std::initializer_list<T> flags)
|
||||
{
|
||||
for (auto flag : flags)
|
||||
{
|
||||
this->set(flag);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const FlagsEnum<T> &other)
|
||||
{
|
||||
return this->value_ == other.value_;
|
||||
}
|
||||
|
||||
bool operator!=(const FlagsEnum &other)
|
||||
{
|
||||
return this->value_ != other.value_;
|
||||
}
|
||||
|
||||
void set(T flag)
|
||||
{
|
||||
reinterpret_cast<Q &>(this->value_) |= static_cast<Q>(flag);
|
||||
}
|
||||
|
||||
void unset(T flag)
|
||||
{
|
||||
reinterpret_cast<Q &>(this->value_) &= ~static_cast<Q>(flag);
|
||||
}
|
||||
|
||||
void set(T flag, bool value)
|
||||
{
|
||||
if (value)
|
||||
this->set(flag);
|
||||
else
|
||||
this->unset(flag);
|
||||
}
|
||||
|
||||
bool has(T flag) const
|
||||
{
|
||||
return static_cast<Q>(this->value_) & static_cast<Q>(flag);
|
||||
}
|
||||
|
||||
bool hasAny(FlagsEnum flags) const
|
||||
{
|
||||
return static_cast<Q>(this->value_) & static_cast<Q>(flags.value_);
|
||||
}
|
||||
|
||||
bool hasAll(FlagsEnum<T> flags) const
|
||||
{
|
||||
return (static_cast<Q>(this->value_) & static_cast<Q>(flags.value_)) &&
|
||||
static_cast<Q>(flags->value);
|
||||
}
|
||||
|
||||
bool hasNone(std::initializer_list<T> flags) const
|
||||
{
|
||||
return !this->hasAny(flags);
|
||||
}
|
||||
|
||||
private:
|
||||
T value_{};
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
+176
-42
@@ -1,67 +1,201 @@
|
||||
#include "common/LinkParser.hpp"
|
||||
|
||||
#include <QFile>
|
||||
#include <QMap>
|
||||
#include <QRegularExpression>
|
||||
#include <QString>
|
||||
#include <QStringRef>
|
||||
#include <QTextStream>
|
||||
|
||||
// ip 0.0.0.0 - 224.0.0.0
|
||||
#define IP \
|
||||
"(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" \
|
||||
"(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" \
|
||||
"(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))"
|
||||
#define PORT "(?::\\d{2,5})"
|
||||
#define WEB_CHAR1 "[_a-z\\x{00a1}-\\x{ffff}0-9]"
|
||||
#define WEB_CHAR2 "[a-z\\x{00a1}-\\x{ffff}0-9]"
|
||||
|
||||
#define SPOTIFY_1 "(?:artist|album|track|user:[^:]+:playlist):[a-zA-Z0-9]+"
|
||||
#define SPOTIFY_2 "user:[^:]+"
|
||||
#define SPOTIFY_3 "search:(?:[-\\w$\\.+!*'(),]+|%[a-fA-F0-9]{2})+"
|
||||
#define SPOTIFY_PARAMS "(?:" SPOTIFY_1 "|" SPOTIFY_2 "|" SPOTIFY_3 ")"
|
||||
#define SPOTIFY_LINK "(?x-mi:(spotify:" SPOTIFY_PARAMS "))"
|
||||
|
||||
#define WEB_PROTOCOL "(?:(?:https?|ftps?)://)?"
|
||||
#define WEB_USER "(?:\\S+(?::\\S*)?@)?"
|
||||
#define WEB_HOST "(?:(?:" WEB_CHAR1 "-*)*" WEB_CHAR2 "+)"
|
||||
#define WEB_DOMAIN "(?:\\.(?:" WEB_CHAR2 "-*)*" WEB_CHAR2 "+)*"
|
||||
#define WEB_TLD "(?:" + tldData + ")"
|
||||
#define WEB_RESOURCE_PATH "(?:[/?#]\\S*)"
|
||||
#define WEB_LINK \
|
||||
WEB_PROTOCOL WEB_USER "(?:" IP "|" WEB_HOST WEB_DOMAIN "\\." WEB_TLD PORT \
|
||||
"?" WEB_RESOURCE_PATH "?)"
|
||||
|
||||
#define LINK "^(?:" SPOTIFY_LINK "|" WEB_LINK ")$"
|
||||
|
||||
namespace chatterino {
|
||||
namespace {
|
||||
QSet<QString> &tlds()
|
||||
{
|
||||
static QSet<QString> tlds = [] {
|
||||
QFile file(":/tlds.txt");
|
||||
file.open(QFile::ReadOnly);
|
||||
QTextStream stream(&file);
|
||||
stream.setCodec("UTF-8");
|
||||
int safetyMax = 20000;
|
||||
|
||||
QSet<QString> set;
|
||||
|
||||
while (!stream.atEnd())
|
||||
{
|
||||
auto line = stream.readLine();
|
||||
set.insert(line);
|
||||
|
||||
if (safetyMax-- == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return set;
|
||||
}();
|
||||
return tlds;
|
||||
}
|
||||
|
||||
bool isValidHostname(QStringRef &host)
|
||||
{
|
||||
int index = host.lastIndexOf('.');
|
||||
|
||||
return index != -1 &&
|
||||
tlds().contains(host.mid(index + 1).toString().toLower());
|
||||
}
|
||||
|
||||
bool isValidIpv4(QStringRef &host)
|
||||
{
|
||||
static auto exp = QRegularExpression("^\\d{1,3}(?:\\.\\d{1,3}){3}$");
|
||||
|
||||
return exp.match(host).hasMatch();
|
||||
}
|
||||
|
||||
#ifdef C_MATCH_IPV6_LINK
|
||||
bool isValidIpv6(QStringRef &host)
|
||||
{
|
||||
static auto exp = QRegularExpression("^\\[[a-fA-F0-9:%]+\\]$");
|
||||
|
||||
return exp.match(host).hasMatch();
|
||||
}
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
LinkParser::LinkParser(const QString &unparsedString)
|
||||
{
|
||||
static QRegularExpression linkRegex = [] {
|
||||
static QRegularExpression newLineRegex("\r?\n");
|
||||
QFile file(":/tlds.txt");
|
||||
file.open(QFile::ReadOnly);
|
||||
QTextStream tlds(&file);
|
||||
tlds.setCodec("UTF-8");
|
||||
this->match_ = unparsedString;
|
||||
|
||||
// tldData gets injected into the LINK macro
|
||||
auto tldData = tlds.readAll().replace(newLineRegex, "|");
|
||||
(void)tldData;
|
||||
// This is not implemented with a regex to increase performance.
|
||||
// We keep removing parts of the url until there's either nothing left or we fail.
|
||||
QStringRef l(&unparsedString);
|
||||
|
||||
return QRegularExpression(LINK,
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
}();
|
||||
bool hasHttp = false;
|
||||
|
||||
this->match_ = linkRegex.match(unparsedString);
|
||||
// Protocol `https?://`
|
||||
if (l.startsWith("https://", Qt::CaseInsensitive))
|
||||
{
|
||||
hasHttp = true;
|
||||
l = l.mid(8);
|
||||
}
|
||||
else if (l.startsWith("http://", Qt::CaseInsensitive))
|
||||
{
|
||||
hasHttp = true;
|
||||
l = l.mid(7);
|
||||
}
|
||||
|
||||
// Http basic auth `user:password`.
|
||||
// Not supported for security reasons (misleading links)
|
||||
|
||||
// Host `a.b.c.com`
|
||||
QStringRef host = l;
|
||||
bool lastWasDot = true;
|
||||
bool inIpv6 = false;
|
||||
|
||||
for (int i = 0; i < l.size(); i++)
|
||||
{
|
||||
if (l[i] == '.')
|
||||
{
|
||||
if (lastWasDot == true) // no double dots ..
|
||||
goto error;
|
||||
lastWasDot = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastWasDot = false;
|
||||
}
|
||||
|
||||
if (l[i] == ':' && !inIpv6)
|
||||
{
|
||||
host = l.mid(0, i);
|
||||
l = l.mid(i + 1);
|
||||
goto parsePort;
|
||||
}
|
||||
else if (l[i] == '/')
|
||||
{
|
||||
host = l.mid(0, i);
|
||||
l = l.mid(i + 1);
|
||||
goto parsePath;
|
||||
}
|
||||
else if (l[i] == '?')
|
||||
{
|
||||
host = l.mid(0, i);
|
||||
l = l.mid(i + 1);
|
||||
goto parseQuery;
|
||||
}
|
||||
else if (l[i] == '#')
|
||||
{
|
||||
host = l.mid(0, i);
|
||||
l = l.mid(i + 1);
|
||||
goto parseAnchor;
|
||||
}
|
||||
|
||||
// ipv6
|
||||
if (l[i] == '[')
|
||||
{
|
||||
if (i == 0)
|
||||
inIpv6 = true;
|
||||
else
|
||||
goto error;
|
||||
}
|
||||
else if (l[i] == ']')
|
||||
{
|
||||
inIpv6 = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastWasDot)
|
||||
goto error;
|
||||
else
|
||||
goto done;
|
||||
|
||||
parsePort:
|
||||
// Port `:12345`
|
||||
for (int i = 0; i < std::min<int>(5, l.size()); i++)
|
||||
{
|
||||
if (l[i] == '/')
|
||||
goto parsePath;
|
||||
else if (l[i] == '?')
|
||||
goto parseQuery;
|
||||
else if (l[i] == '#')
|
||||
goto parseAnchor;
|
||||
|
||||
if (!l[i].isDigit())
|
||||
goto error;
|
||||
}
|
||||
|
||||
goto done;
|
||||
|
||||
parsePath:
|
||||
parseQuery:
|
||||
parseAnchor:
|
||||
// we accept everything in the path/query/anchor
|
||||
|
||||
done:
|
||||
// check host
|
||||
this->hasMatch_ = isValidHostname(host) || isValidIpv4(host)
|
||||
#ifdef C_MATCH_IPV6_LINK
|
||||
|
||||
|| (hasHttp && isValidIpv6(host))
|
||||
#endif
|
||||
;
|
||||
|
||||
if (this->hasMatch_)
|
||||
{
|
||||
this->match_ = unparsedString;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
hasMatch_ = false;
|
||||
}
|
||||
|
||||
bool LinkParser::hasMatch() const
|
||||
{
|
||||
return this->match_.hasMatch();
|
||||
return this->hasMatch_;
|
||||
}
|
||||
|
||||
QString LinkParser::getCaptured() const
|
||||
{
|
||||
return this->match_.captured();
|
||||
return this->match_;
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -14,7 +14,8 @@ public:
|
||||
QString getCaptured() const;
|
||||
|
||||
private:
|
||||
QRegularExpressionMatch match_;
|
||||
bool hasMatch_{false};
|
||||
QString match_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -27,7 +27,7 @@ Modes::Modes()
|
||||
}
|
||||
}
|
||||
|
||||
const Modes &Modes::getInstance()
|
||||
const Modes &Modes::instance()
|
||||
{
|
||||
static Modes instance;
|
||||
return instance;
|
||||
|
||||
@@ -7,7 +7,7 @@ class Modes
|
||||
public:
|
||||
Modes();
|
||||
|
||||
static const Modes &getInstance();
|
||||
static const Modes &instance();
|
||||
|
||||
bool isNightly{};
|
||||
bool isPortable{};
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
struct SuccessTag {
|
||||
};
|
||||
|
||||
struct FailureTag {
|
||||
};
|
||||
|
||||
const SuccessTag Success{};
|
||||
const FailureTag Failure{};
|
||||
|
||||
class Outcome
|
||||
{
|
||||
public:
|
||||
Outcome(SuccessTag)
|
||||
: success_(true)
|
||||
{
|
||||
}
|
||||
|
||||
Outcome(FailureTag)
|
||||
: success_(false)
|
||||
{
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return this->success_;
|
||||
}
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return !this->success_;
|
||||
}
|
||||
|
||||
bool operator==(const Outcome &other) const
|
||||
{
|
||||
return this->success_ == other.success_;
|
||||
}
|
||||
|
||||
bool operator!=(const Outcome &other) const
|
||||
{
|
||||
return !this->operator==(other);
|
||||
}
|
||||
|
||||
private:
|
||||
bool success_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class Settings;
|
||||
class Paths;
|
||||
|
||||
class Singleton : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
virtual ~Singleton() = default;
|
||||
|
||||
virtual void initialize(Settings &settings, Paths &paths)
|
||||
{
|
||||
(void)(settings);
|
||||
(void)(paths);
|
||||
}
|
||||
|
||||
virtual void save()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
+9
-13
@@ -16,50 +16,46 @@ Version::Version()
|
||||
this->commitHash_ =
|
||||
QString(FROM_EXTERNAL_DEFINE(CHATTERINO_GIT_HASH)).remove('"');
|
||||
|
||||
// Date of build
|
||||
// Date of build, this is depended on the format not changing
|
||||
#ifdef CHATTERINO_NIGHTLY_VERSION_STRING
|
||||
this->dateOfBuild_ =
|
||||
QString(FROM_EXTERNAL_DEFINE(CHATTERINO_NIGHTLY_VERSION_STRING))
|
||||
.remove('"');
|
||||
.remove('"')
|
||||
.split(' ')[0];
|
||||
#endif
|
||||
|
||||
// "Full" version string, as displayed in window title
|
||||
this->fullVersion_ = "Chatterino ";
|
||||
if (Modes::getInstance().isNightly)
|
||||
if (Modes::instance().isNightly)
|
||||
{
|
||||
this->fullVersion_ += "Nightly ";
|
||||
}
|
||||
|
||||
this->fullVersion_ += this->version_;
|
||||
|
||||
if (Modes::getInstance().isNightly)
|
||||
{
|
||||
this->fullVersion_ += this->dateOfBuild_;
|
||||
}
|
||||
}
|
||||
|
||||
const Version &Version::getInstance()
|
||||
const Version &Version::instance()
|
||||
{
|
||||
static Version instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
const QString &Version::getVersion() const
|
||||
const QString &Version::version() const
|
||||
{
|
||||
return this->version_;
|
||||
}
|
||||
|
||||
const QString &Version::getFullVersion() const
|
||||
const QString &Version::fullVersion() const
|
||||
{
|
||||
return this->fullVersion_;
|
||||
}
|
||||
|
||||
const QString &Version::getCommitHash() const
|
||||
const QString &Version::commitHash() const
|
||||
{
|
||||
return this->commitHash_;
|
||||
}
|
||||
|
||||
const QString &Version::getDateOfBuild() const
|
||||
const QString &Version::dateOfBuild() const
|
||||
{
|
||||
return this->dateOfBuild_;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QtGlobal>
|
||||
|
||||
#define CHATTERINO_VERSION "2.1.4"
|
||||
#define CHATTERINO_VERSION "2.1.7"
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
# define CHATTERINO_OS "win"
|
||||
@@ -19,12 +20,12 @@ namespace chatterino {
|
||||
class Version
|
||||
{
|
||||
public:
|
||||
static const Version &getInstance();
|
||||
static const Version &instance();
|
||||
|
||||
const QString &getVersion() const;
|
||||
const QString &getCommitHash() const;
|
||||
const QString &getDateOfBuild() const;
|
||||
const QString &getFullVersion() const;
|
||||
const QString &version() const;
|
||||
const QString &commitHash() const;
|
||||
const QString &dateOfBuild() const;
|
||||
const QString &fullVersion() const;
|
||||
|
||||
private:
|
||||
Version();
|
||||
@@ -35,4 +36,4 @@ private:
|
||||
QString fullVersion_;
|
||||
};
|
||||
|
||||
};
|
||||
}; // namespace chatterino
|
||||
|
||||
Reference in New Issue
Block a user