Merge branch '4tf'
|
@ -17,6 +17,10 @@ DEFINES += QT_DEPRECATED_WARNINGS
|
|||
PRECOMPILED_HEADER = src/PrecompiledHeader.hpp
|
||||
CONFIG += precompile_header
|
||||
|
||||
debug {
|
||||
DEFINES += QT_DEBUG
|
||||
}
|
||||
|
||||
useBreakpad {
|
||||
LIBS += -L$$PWD/lib/qBreakpad/handler/build
|
||||
include(lib/qBreakpad/qBreakpad.pri)
|
||||
|
@ -132,9 +136,7 @@ SOURCES += \
|
|||
src/messages/MessageBuilder.cpp \
|
||||
src/messages/MessageColor.cpp \
|
||||
src/messages/MessageElement.cpp \
|
||||
src/providers/bttv/BttvEmotes.cpp \
|
||||
src/providers/emoji/Emojis.cpp \
|
||||
src/providers/ffz/FfzEmotes.cpp \
|
||||
src/providers/irc/AbstractIrcServer.cpp \
|
||||
src/providers/irc/IrcAccount.cpp \
|
||||
src/providers/irc/IrcChannel2.cpp \
|
||||
|
@ -232,7 +234,21 @@ SOURCES += \
|
|||
src/widgets/dialogs/UpdateDialog.cpp \
|
||||
src/widgets/settingspages/IgnoresPage.cpp \
|
||||
src/providers/twitch/PubsubClient.cpp \
|
||||
src/providers/twitch/TwitchApi.cpp
|
||||
src/providers/twitch/TwitchApi.cpp \
|
||||
src/messages/Emote.cpp \
|
||||
src/messages/EmoteMap.cpp \
|
||||
src/messages/ImageSet.cpp \
|
||||
src/providers/bttv/BttvEmotes.cpp \
|
||||
src/providers/ffz/FfzEmotes.cpp \
|
||||
src/autogenerated/ResourcesAutogen.cpp \
|
||||
src/singletons/Badges.cpp \
|
||||
src/providers/twitch/TwitchBadges.cpp \
|
||||
src/providers/chatterino/ChatterinoBadges.cpp \
|
||||
src/providers/twitch/TwitchParseCheerEmotes.cpp \
|
||||
src/providers/bttv/LoadBttvChannelEmote.cpp \
|
||||
src/util/JsonQuery.cpp \
|
||||
src/RunGui.cpp \
|
||||
src/BrowserExtension.cpp
|
||||
|
||||
HEADERS += \
|
||||
src/Application.hpp \
|
||||
|
@ -292,9 +308,7 @@ HEADERS += \
|
|||
src/messages/MessageParseArgs.hpp \
|
||||
src/messages/Selection.hpp \
|
||||
src/PrecompiledHeader.hpp \
|
||||
src/providers/bttv/BttvEmotes.hpp \
|
||||
src/providers/emoji/Emojis.hpp \
|
||||
src/providers/ffz/FfzEmotes.hpp \
|
||||
src/providers/irc/AbstractIrcServer.hpp \
|
||||
src/providers/irc/IrcAccount.hpp \
|
||||
src/providers/irc/IrcChannel2.hpp \
|
||||
|
@ -413,10 +427,28 @@ HEADERS += \
|
|||
src/widgets/dialogs/UpdateDialog.hpp \
|
||||
src/widgets/settingspages/IgnoresPage.hpp \
|
||||
src/providers/twitch/PubsubClient.hpp \
|
||||
src/providers/twitch/TwitchApi.hpp
|
||||
src/providers/twitch/TwitchApi.hpp \
|
||||
src/messages/Emote.hpp \
|
||||
src/messages/EmoteMap.hpp \
|
||||
src/messages/EmoteCache.hpp \
|
||||
src/messages/ImageSet.hpp \
|
||||
src/common/Outcome.hpp \
|
||||
src/providers/bttv/BttvEmotes.hpp \
|
||||
src/providers/ffz/FfzEmotes.hpp \
|
||||
src/autogenerated/ResourcesAutogen.hpp \
|
||||
src/singletons/Badges.hpp \
|
||||
src/providers/twitch/TwitchBadges.hpp \
|
||||
src/providers/chatterino/ChatterinoBadges.hpp \
|
||||
src/common/Aliases.hpp \
|
||||
src/providers/twitch/TwitchParseCheerEmotes.hpp \
|
||||
src/providers/bttv/LoadBttvChannelEmote.hpp \
|
||||
src/util/JsonQuery.hpp \
|
||||
src/RunGui.hpp \
|
||||
src/BrowserExtension.hpp
|
||||
|
||||
RESOURCES += \
|
||||
resources/resources.qrc \
|
||||
resources/resources_autogenerated.qrc
|
||||
|
||||
DISTFILES +=
|
||||
|
||||
|
|
BIN
resources/__pycache__/_generate_resources.cpython-36.pyc
Normal file
38
resources/_generate_resources.py
Normal file
|
@ -0,0 +1,38 @@
|
|||
resources_header = \
|
||||
'''<RCC>
|
||||
<qresource prefix="/">'''
|
||||
|
||||
resources_footer = \
|
||||
''' </qresource>
|
||||
</RCC>'''
|
||||
|
||||
header_header = \
|
||||
'''#include <QPixmap>
|
||||
#include "common/Singleton.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class Resources2 : public Singleton {
|
||||
public:
|
||||
Resources2();
|
||||
|
||||
'''
|
||||
|
||||
header_footer = \
|
||||
'''};
|
||||
|
||||
} // namespace chatterino'''
|
||||
|
||||
source_header = \
|
||||
'''#include "ResourcesAutogen.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
Resources2::Resources2()
|
||||
{
|
||||
'''
|
||||
|
||||
source_footer = \
|
||||
'''}
|
||||
|
||||
} // namespace chatterino'''
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 847 B After Width: | Height: | Size: 847 B |
Before Width: | Height: | Size: 847 B After Width: | Height: | Size: 847 B |
Before Width: | Height: | Size: 307 B After Width: | Height: | Size: 307 B |
Before Width: | Height: | Size: 328 B After Width: | Height: | Size: 328 B |
Before Width: | Height: | Size: 376 B After Width: | Height: | Size: 376 B |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 349 B After Width: | Height: | Size: 349 B |
Before Width: | Height: | Size: 344 B After Width: | Height: | Size: 344 B |
Before Width: | Height: | Size: 332 B After Width: | Height: | Size: 332 B |
BIN
resources/error.png
Normal file
After Width: | Height: | Size: 685 B |
61
resources/generate_resources.py
Executable file
|
@ -0,0 +1,61 @@
|
|||
#!/usr/bin/env python3
|
||||
from pathlib import Path
|
||||
|
||||
from _generate_resources import *
|
||||
|
||||
ignored_files = ['qt.conf', 'resources.qrc', 'resources_autogenerated.qrc', 'windows.rc',
|
||||
'generate_resources.py', '_generate_resources.py']
|
||||
ignored_directories = ['__pycache__']
|
||||
|
||||
def isNotIgnored(file):
|
||||
return str(file) not in ignored_files
|
||||
|
||||
all_files = list(filter(isNotIgnored, \
|
||||
filter(Path.is_file, Path('.').glob('**/*'))))
|
||||
image_files = list(filter(isNotIgnored, \
|
||||
filter(Path.is_file, Path('.').glob('**/*.png'))))
|
||||
|
||||
with open('./resources_autogenerated.qrc', 'w') as out:
|
||||
out.write(resources_header)
|
||||
for file in all_files:
|
||||
out.write(f" <file>{str(file)}</file>\n")
|
||||
out.write(resources_footer)
|
||||
|
||||
with open('../src/autogenerated/ResourcesAutogen.cpp', 'w') as out:
|
||||
out.write(source_header)
|
||||
for file in sorted(image_files):
|
||||
var_name = str(file.with_suffix("")).replace("/",".")
|
||||
out.write(f' this->{var_name}')
|
||||
out.write(f' = QPixmap(":/{file}");\n')
|
||||
out.write(source_footer)
|
||||
|
||||
def writeHeader(out, name, element, indent):
|
||||
if isinstance(element, dict):
|
||||
if name != "":
|
||||
out.write(f"{indent}struct {{\n")
|
||||
for (key, value) in element.items():
|
||||
writeHeader(out, key, value, indent + ' ')
|
||||
if name != "":
|
||||
out.write(f"{indent}}} {name};\n");
|
||||
else:
|
||||
out.write(f"{indent}QPixmap {element};\n")
|
||||
|
||||
with open('../src/autogenerated/ResourcesAutogen.hpp', 'w') as out:
|
||||
out.write(header_header)
|
||||
|
||||
elements = {}
|
||||
for file in sorted(image_files):
|
||||
elements_ref = elements
|
||||
directories = str(file).split('/')[:-1]
|
||||
filename = file.stem
|
||||
for directory in directories:
|
||||
if directory not in elements_ref:
|
||||
if directory not in ignored_directories:
|
||||
elements_ref[directory] = {}
|
||||
elements_ref = elements_ref[directory]
|
||||
elements_ref[filename] = filename
|
||||
|
||||
writeHeader(out, "", elements, '')
|
||||
|
||||
out.write(header_footer)
|
||||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 347 B |
Before Width: | Height: | Size: 680 B |
Before Width: | Height: | Size: 403 B |
Before Width: | Height: | Size: 368 B |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 660 B |
Before Width: | Height: | Size: 280 B |
Before Width: | Height: | Size: 179 B |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 286 B |
Before Width: | Height: | Size: 480 B |
Before Width: | Height: | Size: 360 B |
Before Width: | Height: | Size: 351 B |
Before Width: | Height: | Size: 330 B |
Before Width: | Height: | Size: 285 B |
Before Width: | Height: | Size: 362 B |
Before Width: | Height: | Size: 236 B |
Before Width: | Height: | Size: 354 B |
Before Width: | Height: | Size: 274 B |
Before Width: | Height: | Size: 279 B |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
@ -1,81 +1,4 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>images/AppearanceEditorPart_16x.png</file>
|
||||
<file>images/BrowserLink_16x.png</file>
|
||||
<file>images/cheer1.png</file>
|
||||
<file>images/cheer100.png</file>
|
||||
<file>images/cheer1000.png</file>
|
||||
<file>images/cheer10000.png</file>
|
||||
<file>images/cheer100000.png</file>
|
||||
<file>images/cheer5000.png</file>
|
||||
<file>images/verified.png</file>
|
||||
<file>images/CopyLongTextToClipboard_16x.png</file>
|
||||
<file>images/CustomActionEditor_16x.png</file>
|
||||
<file>images/Emoji_Color_1F60A_19.png</file>
|
||||
<file>images/Filter_16x.png</file>
|
||||
<file>images/format_Bold_16xLG.png</file>
|
||||
<file>images/Message_16xLG.png</file>
|
||||
<file>images/settings.png</file>
|
||||
<file>images/tool_moreCollapser_off16.png</file>
|
||||
<file>images/twitchprime_bg.png</file>
|
||||
<file>qss/settings.qss</file>
|
||||
<file>images/admin_bg.png</file>
|
||||
<file>images/broadcaster_bg.png</file>
|
||||
<file>images/globalmod_bg.png</file>
|
||||
<file>images/moderator_bg.png</file>
|
||||
<file>images/staff_bg.png</file>
|
||||
<file>images/turbo_bg.png</file>
|
||||
<file>emojidata.txt</file>
|
||||
<file>images/button_ban.png</file>
|
||||
<file>images/button_timeout.png</file>
|
||||
<file>images/StatusAnnotations_Blocked_16xLG_color.png</file>
|
||||
<file>images/UserProfile_22x.png</file>
|
||||
<file>images/VSO_Link_blue_16x.png</file>
|
||||
<file>sounds/ping2.wav</file>
|
||||
<file>images/subscriber.png</file>
|
||||
<file>images/collapse.png</file>
|
||||
<file>images/emote.svg</file>
|
||||
<file>images/notifications.svg</file>
|
||||
<file>images/behave.svg</file>
|
||||
<file>images/theme.svg</file>
|
||||
<file>images/accounts.svg</file>
|
||||
<file>images/chatterino2.icns</file>
|
||||
<file>images/icon.png</file>
|
||||
<file>images/commands.svg</file>
|
||||
<file>images/aboutlogo.png</file>
|
||||
<file>images/about.svg</file>
|
||||
<file>images/moderatormode_disabled.png</file>
|
||||
<file>images/moderatormode_enabled.png</file>
|
||||
<file>images/split/splitdown.png</file>
|
||||
<file>images/split/splitleft.png</file>
|
||||
<file>images/split/splitright.png</file>
|
||||
<file>images/split/splitup.png</file>
|
||||
<file>images/split/splitmove.png</file>
|
||||
<file>licenses/boost_boost.txt</file>
|
||||
<file>licenses/fmt_bsd2.txt</file>
|
||||
<file>licenses/libcommuni_BSD3.txt</file>
|
||||
<file>licenses/openssl.txt</file>
|
||||
<file>licenses/pajlada_settings.txt</file>
|
||||
<file>licenses/pajlada_signals.txt</file>
|
||||
<file>licenses/qt_lgpl-3.0.txt</file>
|
||||
<file>licenses/rapidjson.txt</file>
|
||||
<file>licenses/websocketpp.txt</file>
|
||||
<file>emoji.json</file>
|
||||
<file>images/buttons/ban.png</file>
|
||||
<file>images/buttons/mod.png</file>
|
||||
<file>images/buttons/unban.png</file>
|
||||
<file>images/buttons/unmod.png</file>
|
||||
<file>images/emote_dark.svg</file>
|
||||
<file>tlds.txt</file>
|
||||
<file>images/menu_black.png</file>
|
||||
<file>images/menu_white.png</file>
|
||||
<file>contributors.txt</file>
|
||||
<file>avatars/fourtf.png</file>
|
||||
<file>avatars/pajlada.png</file>
|
||||
<file>images/download_update.png</file>
|
||||
<file>images/download_update_error.png</file>
|
||||
<file>images/pajaDank.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/qt/etc">
|
||||
<file>qt.conf</file>
|
||||
</qresource>
|
||||
|
|
64
resources/resources_autogenerated.qrc
Normal file
|
@ -0,0 +1,64 @@
|
|||
<RCC>
|
||||
<qresource prefix="/"> <file>pajaDank.png</file>
|
||||
<file>icon.png</file>
|
||||
<file>emojidata.txt</file>
|
||||
<file>contributors.txt</file>
|
||||
<file>error.png</file>
|
||||
<file>emoji.json</file>
|
||||
<file>icon.ico</file>
|
||||
<file>tlds.txt</file>
|
||||
<file>chatterino2.icns</file>
|
||||
<file>qss/settings.qss</file>
|
||||
<file>__pycache__/_generate_resources.cpython-36.pyc</file>
|
||||
<file>licenses/fmt_bsd2.txt</file>
|
||||
<file>licenses/openssl.txt</file>
|
||||
<file>licenses/pajlada_settings.txt</file>
|
||||
<file>licenses/qt_lgpl-3.0.txt</file>
|
||||
<file>licenses/pajlada_signals.txt</file>
|
||||
<file>licenses/rapidjson.txt</file>
|
||||
<file>licenses/websocketpp.txt</file>
|
||||
<file>licenses/boost_boost.txt</file>
|
||||
<file>licenses/libcommuni_BSD3.txt</file>
|
||||
<file>settings/aboutlogo.png</file>
|
||||
<file>settings/behave.svg</file>
|
||||
<file>settings/accounts.svg</file>
|
||||
<file>settings/about.svg</file>
|
||||
<file>settings/notifications.svg</file>
|
||||
<file>settings/commands.svg</file>
|
||||
<file>settings/theme.svg</file>
|
||||
<file>split/up.png</file>
|
||||
<file>split/left.png</file>
|
||||
<file>split/move.png</file>
|
||||
<file>split/right.png</file>
|
||||
<file>split/down.png</file>
|
||||
<file>buttons/unban.png</file>
|
||||
<file>buttons/menuDark.png</file>
|
||||
<file>buttons/mod.png</file>
|
||||
<file>buttons/emote.svg</file>
|
||||
<file>buttons/modModeEnabled2.png</file>
|
||||
<file>buttons/ban.png</file>
|
||||
<file>buttons/unmod.png</file>
|
||||
<file>buttons/emoteDark.svg</file>
|
||||
<file>buttons/updateError.png</file>
|
||||
<file>buttons/modModeDisabled.png</file>
|
||||
<file>buttons/modModeDisabled2.png</file>
|
||||
<file>buttons/modModeEnabled.png</file>
|
||||
<file>buttons/menuLight.png</file>
|
||||
<file>buttons/update.png</file>
|
||||
<file>buttons/timeout.png</file>
|
||||
<file>buttons/banRed.png</file>
|
||||
<file>sounds/ping2.wav</file>
|
||||
<file>twitch/prime.png</file>
|
||||
<file>twitch/verified.png</file>
|
||||
<file>twitch/admin.png</file>
|
||||
<file>twitch/subscriber.png</file>
|
||||
<file>twitch/turbo.png</file>
|
||||
<file>twitch/moderator.png</file>
|
||||
<file>twitch/globalmod.png</file>
|
||||
<file>twitch/cheer1.png</file>
|
||||
<file>twitch/broadcaster.png</file>
|
||||
<file>twitch/staff.png</file>
|
||||
<file>avatars/fourtf.png</file>
|
||||
<file>avatars/pajlada.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 805 B After Width: | Height: | Size: 805 B |
Before Width: | Height: | Size: 820 B After Width: | Height: | Size: 820 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 955 B After Width: | Height: | Size: 955 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 361 B After Width: | Height: | Size: 361 B |
Before Width: | Height: | Size: 437 B After Width: | Height: | Size: 437 B |
Before Width: | Height: | Size: 772 B After Width: | Height: | Size: 772 B |
Before Width: | Height: | Size: 494 B After Width: | Height: | Size: 494 B |
Before Width: | Height: | Size: 361 B After Width: | Height: | Size: 361 B |
Before Width: | Height: | Size: 439 B After Width: | Height: | Size: 439 B |
Before Width: | Height: | Size: 191 B After Width: | Height: | Size: 191 B |
Before Width: | Height: | Size: 255 B After Width: | Height: | Size: 255 B |
Before Width: | Height: | Size: 397 B After Width: | Height: | Size: 397 B |
Before Width: | Height: | Size: 376 B After Width: | Height: | Size: 376 B |
Before Width: | Height: | Size: 116 B After Width: | Height: | Size: 116 B |
Before Width: | Height: | Size: 269 B After Width: | Height: | Size: 269 B |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 257 B After Width: | Height: | Size: 257 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
@ -6,9 +6,10 @@
|
|||
#include "controllers/ignores/IgnoreController.hpp"
|
||||
#include "controllers/moderationactions/ModerationActions.hpp"
|
||||
#include "controllers/taggedusers/TaggedUsersController.hpp"
|
||||
#include "providers/bttv/BttvEmotes.hpp"
|
||||
#include "providers/ffz/FfzEmotes.hpp"
|
||||
#include "providers/twitch/PubsubClient.hpp"
|
||||
#include "providers/twitch/TwitchServer.hpp"
|
||||
#include "singletons/Emotes.hpp"
|
||||
#include "singletons/Fonts.hpp"
|
||||
#include "singletons/Logging.hpp"
|
||||
#include "singletons/NativeMessaging.hpp"
|
||||
|
@ -24,69 +25,75 @@
|
|||
|
||||
namespace chatterino {
|
||||
|
||||
static std::atomic<bool> isAppConstructed{false};
|
||||
static std::atomic<bool> isAppInitialized{false};
|
||||
|
||||
static Application *staticApp = nullptr;
|
||||
Application *Application::instance = nullptr;
|
||||
|
||||
// this class is responsible for handling the workflow of Chatterino
|
||||
// It will create the instances of the major classes, and connect their signals to each other
|
||||
|
||||
Application::Application(int _argc, char **_argv)
|
||||
: argc_(_argc)
|
||||
, argv_(_argv)
|
||||
Application::Application(Settings &_settings, Paths &_paths)
|
||||
: settings(&_settings)
|
||||
, paths(&_paths)
|
||||
, resources(&this->emplace<Resources2>())
|
||||
|
||||
, themes(&this->emplace<Theme>())
|
||||
, fonts(&this->emplace<Fonts>())
|
||||
, emotes(&this->emplace<Emotes>())
|
||||
, windows(&this->emplace<WindowManager>())
|
||||
|
||||
, accounts(&this->emplace<AccountController>())
|
||||
, commands(&this->emplace<CommandController>())
|
||||
, highlights(&this->emplace<HighlightController>())
|
||||
, ignores(&this->emplace<IgnoreController>())
|
||||
, taggedUsers(&this->emplace<TaggedUsersController>())
|
||||
, moderationActions(&this->emplace<ModerationActions>())
|
||||
, twitch2(&this->emplace<TwitchServer>())
|
||||
, logging(&this->emplace<Logging>())
|
||||
{
|
||||
getSettings()->initialize();
|
||||
getSettings()->load();
|
||||
}
|
||||
this->instance = this;
|
||||
|
||||
void Application::construct()
|
||||
{
|
||||
assert(isAppConstructed == false);
|
||||
isAppConstructed = true;
|
||||
this->fonts->fontChanged.connect([this]() { this->windows->layoutChannelViews(); });
|
||||
|
||||
// 1. Instantiate all classes
|
||||
this->settings = getSettings();
|
||||
this->paths = getPaths();
|
||||
|
||||
this->addSingleton(this->themes = new Theme);
|
||||
this->addSingleton(this->windows = new WindowManager);
|
||||
this->addSingleton(this->logging = new Logging);
|
||||
this->addSingleton(this->commands = new CommandController);
|
||||
this->addSingleton(this->highlights = new HighlightController);
|
||||
this->addSingleton(this->ignores = new IgnoreController);
|
||||
this->addSingleton(this->taggedUsers = new TaggedUsersController);
|
||||
this->addSingleton(this->accounts = new AccountController);
|
||||
this->addSingleton(this->emotes = new Emotes);
|
||||
this->addSingleton(this->fonts = new Fonts);
|
||||
this->addSingleton(this->resources = new Resources);
|
||||
this->addSingleton(this->moderationActions = new ModerationActions);
|
||||
|
||||
this->addSingleton(this->twitch2 = new TwitchServer);
|
||||
this->twitch.server = this->twitch2;
|
||||
this->twitch.pubsub = this->twitch2->pubsub;
|
||||
}
|
||||
|
||||
void Application::instantiate(int argc, char **argv)
|
||||
{
|
||||
assert(staticApp == nullptr);
|
||||
|
||||
staticApp = new Application(argc, argv);
|
||||
}
|
||||
|
||||
void Application::initialize()
|
||||
void Application::initialize(Settings &settings, Paths &paths)
|
||||
{
|
||||
assert(isAppInitialized == false);
|
||||
isAppInitialized = true;
|
||||
|
||||
// 2. Initialize/load classes
|
||||
for (Singleton *singleton : this->singletons_) {
|
||||
singleton->initialize(*this);
|
||||
for (auto &singleton : this->singletons_) {
|
||||
singleton->initialize(settings, paths);
|
||||
}
|
||||
|
||||
// XXX
|
||||
this->windows->updateWordTypeMask();
|
||||
|
||||
this->initNm();
|
||||
this->initPubsub();
|
||||
}
|
||||
|
||||
int Application::run(QApplication &qtApp)
|
||||
{
|
||||
assert(isAppInitialized);
|
||||
|
||||
this->twitch.server->connect();
|
||||
|
||||
this->windows->getMainWindow().show();
|
||||
|
||||
return qtApp.exec();
|
||||
}
|
||||
|
||||
void Application::save()
|
||||
{
|
||||
for (auto &singleton : this->singletons_) {
|
||||
singleton->save();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::initNm()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
#ifdef QT_DEBUG
|
||||
#ifdef C_DEBUG_NM
|
||||
|
@ -98,7 +105,10 @@ void Application::initialize()
|
|||
this->nativeMessaging->openGuiMessageQueue();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void Application::initPubsub()
|
||||
{
|
||||
this->twitch.pubsub->signals_.whisper.sent.connect([](const auto &msg) {
|
||||
Log("WHISPER SENT LOL"); //
|
||||
});
|
||||
|
@ -197,39 +207,11 @@ void Application::initialize()
|
|||
RequestModerationActions();
|
||||
}
|
||||
|
||||
int Application::run(QApplication &qtApp)
|
||||
{
|
||||
// Start connecting to the IRC Servers (Twitch only for now)
|
||||
this->twitch.server->connect();
|
||||
|
||||
// Show main window
|
||||
this->windows->getMainWindow().show();
|
||||
|
||||
return qtApp.exec();
|
||||
}
|
||||
|
||||
void Application::save()
|
||||
{
|
||||
for (Singleton *singleton : this->singletons_) {
|
||||
singleton->save();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::addSingleton(Singleton *singleton)
|
||||
{
|
||||
this->singletons_.push_back(singleton);
|
||||
}
|
||||
|
||||
Application *getApp()
|
||||
{
|
||||
assert(staticApp != nullptr);
|
||||
assert(Application::instance != nullptr);
|
||||
|
||||
return staticApp;
|
||||
}
|
||||
|
||||
bool appInitialized()
|
||||
{
|
||||
return isAppInitialized;
|
||||
return Application::instance;
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "common/Singleton.hpp"
|
||||
#include "singletons/Resources.hpp"
|
||||
|
||||
#include <QApplication>
|
||||
#include <memory>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class Singleton;
|
||||
|
||||
class TwitchServer;
|
||||
class PubSub;
|
||||
|
||||
|
@ -24,45 +24,47 @@ class Logging;
|
|||
class Paths;
|
||||
class AccountManager;
|
||||
class Emotes;
|
||||
class NativeMessaging;
|
||||
class Settings;
|
||||
class Fonts;
|
||||
class Resources;
|
||||
|
||||
class Application
|
||||
{
|
||||
Application(int _argc, char **_argv);
|
||||
std::vector<std::unique_ptr<Singleton>> singletons_;
|
||||
int argc_;
|
||||
char **argv_;
|
||||
|
||||
public:
|
||||
static void instantiate(int argc_, char **argv_);
|
||||
static Application *instance;
|
||||
|
||||
~Application() = delete;
|
||||
Application(Settings &settings, Paths &paths);
|
||||
|
||||
void construct();
|
||||
void initialize();
|
||||
void initialize(Settings &settings, Paths &paths);
|
||||
void load();
|
||||
void save();
|
||||
|
||||
int run(QApplication &qtApp);
|
||||
|
||||
friend void test();
|
||||
|
||||
[[deprecated("use getSettings() instead")]] Settings *settings = nullptr;
|
||||
[[deprecated("use getPaths() instead")]] Paths *paths = nullptr;
|
||||
Settings *const settings = nullptr;
|
||||
Paths *const paths = nullptr;
|
||||
Resources2 *const resources;
|
||||
|
||||
Theme *themes = nullptr;
|
||||
WindowManager *windows = nullptr;
|
||||
Logging *logging = nullptr;
|
||||
CommandController *commands = nullptr;
|
||||
HighlightController *highlights = nullptr;
|
||||
IgnoreController *ignores = nullptr;
|
||||
TaggedUsersController *taggedUsers = nullptr;
|
||||
AccountController *accounts = nullptr;
|
||||
Emotes *emotes = nullptr;
|
||||
NativeMessaging *nativeMessaging = nullptr;
|
||||
Fonts *fonts = nullptr;
|
||||
Resources *resources = nullptr;
|
||||
ModerationActions *moderationActions = nullptr;
|
||||
TwitchServer *twitch2 = nullptr;
|
||||
Theme *const themes = nullptr;
|
||||
Fonts *const fonts = nullptr;
|
||||
Emotes *const emotes = nullptr;
|
||||
WindowManager *const windows = nullptr;
|
||||
|
||||
AccountController *const accounts = nullptr;
|
||||
CommandController *const commands = nullptr;
|
||||
HighlightController *const highlights = nullptr;
|
||||
IgnoreController *const ignores = nullptr;
|
||||
TaggedUsersController *const taggedUsers = nullptr;
|
||||
ModerationActions *const moderationActions = nullptr;
|
||||
TwitchServer *const twitch2 = nullptr;
|
||||
|
||||
[[deprecated]] Logging *const logging = nullptr;
|
||||
|
||||
/// Provider-specific
|
||||
struct {
|
||||
|
@ -70,22 +72,20 @@ public:
|
|||
[[deprecated("use twitch2->pubsub instead")]] PubSub *pubsub = nullptr;
|
||||
} twitch;
|
||||
|
||||
void save();
|
||||
|
||||
// Special application mode that only initializes the native messaging host
|
||||
static void runNativeMessagingHost();
|
||||
|
||||
private:
|
||||
void addSingleton(Singleton *singleton);
|
||||
void initPubsub();
|
||||
void initNm();
|
||||
|
||||
int argc_;
|
||||
char **argv_;
|
||||
|
||||
std::vector<Singleton *> singletons_;
|
||||
template <typename T, typename = std::enable_if_t<std::is_base_of<Singleton, T>::value>>
|
||||
T &emplace()
|
||||
{
|
||||
auto t = new T;
|
||||
this->singletons_.push_back(std::unique_ptr<T>(t));
|
||||
return *t;
|
||||
}
|
||||
};
|
||||
|
||||
Application *getApp();
|
||||
|
||||
bool appInitialized();
|
||||
|
||||
} // namespace chatterino
|
||||
|
|
88
src/BrowserExtension.cpp
Normal file
|
@ -0,0 +1,88 @@
|
|||
#include "BrowserExtension.hpp"
|
||||
|
||||
#include "singletons/NativeMessaging.hpp"
|
||||
|
||||
#include <QStringList>
|
||||
#include <QTimer>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
namespace {
|
||||
void initFileMode()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
_setmode(_fileno(stdin), _O_BINARY);
|
||||
_setmode(_fileno(stdout), _O_BINARY);
|
||||
#endif
|
||||
}
|
||||
|
||||
void runLoop(NativeMessagingClient &client)
|
||||
{
|
||||
while (true) {
|
||||
char size_c[4];
|
||||
std::cin.read(size_c, 4);
|
||||
|
||||
if (std::cin.eof()) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t size = *reinterpret_cast<uint32_t *>(size_c);
|
||||
|
||||
#if 0
|
||||
bool bigEndian = isBigEndian();
|
||||
// To avoid breaking strict-aliasing rules and potentially inducing undefined behaviour, the following code can be run instead
|
||||
uint32_t size = 0;
|
||||
if (bigEndian) {
|
||||
size = size_c[3] | static_cast<uint32_t>(size_c[2]) << 8 |
|
||||
static_cast<uint32_t>(size_c[1]) << 16 | static_cast<uint32_t>(size_c[0]) << 24;
|
||||
} else {
|
||||
size = size_c[0] | static_cast<uint32_t>(size_c[1]) << 8 |
|
||||
static_cast<uint32_t>(size_c[2]) << 16 | static_cast<uint32_t>(size_c[3]) << 24;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<char[]> b(new char[size + 1]);
|
||||
std::cin.read(b.get(), size);
|
||||
*(b.get() + size) = '\0';
|
||||
|
||||
client.sendMessage(QByteArray::fromRawData(b.get(), static_cast<int32_t>(size)));
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool shouldRunBrowserExtensionHost(const QStringList &args)
|
||||
{
|
||||
return args.size() > 0 &&
|
||||
(args[0].startsWith("chrome-extension://") || args[0].endsWith(".json"));
|
||||
}
|
||||
|
||||
void runBrowserExtensionHost()
|
||||
{
|
||||
initFileMode();
|
||||
|
||||
std::atomic<bool> ping(false);
|
||||
|
||||
QTimer timer;
|
||||
QObject::connect(&timer, &QTimer::timeout, [&ping] {
|
||||
if (!ping.exchange(false)) {
|
||||
_Exit(0);
|
||||
}
|
||||
});
|
||||
timer.setInterval(11000);
|
||||
timer.start();
|
||||
|
||||
NativeMessagingClient client;
|
||||
|
||||
runLoop(client);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
10
src/BrowserExtension.hpp
Normal file
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
class QStringList;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
bool shouldRunBrowserExtensionHost(const QStringList &args);
|
||||
void runBrowserExtensionHost();
|
||||
|
||||
} // namespace chatterino
|
130
src/RunGui.cpp
Normal file
|
@ -0,0 +1,130 @@
|
|||
#include "RunGui.hpp"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QFile>
|
||||
#include <QPalette>
|
||||
#include <QStyleFactory>
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "common/NetworkManager.hpp"
|
||||
#include "singletons/Paths.hpp"
|
||||
#include "singletons/Updates.hpp"
|
||||
#include "widgets/dialogs/LastRunCrashDialog.hpp"
|
||||
|
||||
#ifdef C_USE_BREAKPAD
|
||||
#include <QBreakpadHandler.h>
|
||||
#endif
|
||||
|
||||
// void initQt();
|
||||
// void installCustomPalette();
|
||||
// void showLastCrashDialog();
|
||||
// void createRunningFile(const QString &path);
|
||||
// void removeRunningFile(const QString &path);
|
||||
|
||||
namespace chatterino {
|
||||
namespace {
|
||||
void installCustomPalette()
|
||||
{
|
||||
// borrowed from
|
||||
// https://stackoverflow.com/questions/15035767/is-the-qt-5-dark-fusion-theme-available-for-windows
|
||||
QPalette darkPalette = qApp->palette();
|
||||
|
||||
darkPalette.setColor(QPalette::Window, QColor(22, 22, 22));
|
||||
darkPalette.setColor(QPalette::WindowText, Qt::white);
|
||||
darkPalette.setColor(QPalette::Text, Qt::white);
|
||||
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, QColor(127, 127, 127));
|
||||
darkPalette.setColor(QPalette::Base, QColor("#333"));
|
||||
darkPalette.setColor(QPalette::AlternateBase, QColor("#444"));
|
||||
darkPalette.setColor(QPalette::ToolTipBase, Qt::white);
|
||||
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
|
||||
darkPalette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127));
|
||||
darkPalette.setColor(QPalette::Dark, QColor(35, 35, 35));
|
||||
darkPalette.setColor(QPalette::Shadow, QColor(20, 20, 20));
|
||||
darkPalette.setColor(QPalette::Button, QColor(70, 70, 70));
|
||||
darkPalette.setColor(QPalette::ButtonText, Qt::white);
|
||||
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(127, 127, 127));
|
||||
darkPalette.setColor(QPalette::BrightText, Qt::red);
|
||||
darkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
|
||||
darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
|
||||
darkPalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(80, 80, 80));
|
||||
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
|
||||
darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(127, 127, 127));
|
||||
|
||||
qApp->setPalette(darkPalette);
|
||||
}
|
||||
|
||||
void initQt()
|
||||
{
|
||||
// set up the QApplication flags
|
||||
QApplication::setAttribute(Qt::AA_Use96Dpi, true);
|
||||
#ifdef Q_OS_WIN32
|
||||
QApplication::setAttribute(Qt::AA_DisableHighDpiScaling, true);
|
||||
#endif
|
||||
|
||||
QApplication::setStyle(QStyleFactory::create("Fusion"));
|
||||
|
||||
installCustomPalette();
|
||||
}
|
||||
|
||||
void showLastCrashDialog()
|
||||
{
|
||||
#ifndef C_DISABLE_CRASH_DIALOG
|
||||
LastRunCrashDialog dialog;
|
||||
|
||||
switch (dialog.exec()) {
|
||||
case QDialog::Accepted: {
|
||||
}; break;
|
||||
default: {
|
||||
_exit(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void createRunningFile(const QString &path)
|
||||
{
|
||||
QFile runningFile(path);
|
||||
|
||||
runningFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
|
||||
runningFile.flush();
|
||||
runningFile.close();
|
||||
}
|
||||
|
||||
void removeRunningFile(const QString &path)
|
||||
{
|
||||
QFile::remove(path);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void runGui(QApplication &a, Paths &paths, Settings &settings)
|
||||
{
|
||||
chatterino::NetworkManager::init();
|
||||
chatterino::Updates::getInstance().checkForUpdates();
|
||||
|
||||
#ifdef C_USE_BREAKPAD
|
||||
QBreakpadInstance.setDumpPath(app->paths->settingsFolderPath + "/Crashes");
|
||||
#endif
|
||||
|
||||
// Running file
|
||||
auto runningPath = paths.miscDirectory + "/running_" + paths.applicationFilePathHash;
|
||||
|
||||
if (QFile::exists(runningPath)) {
|
||||
showLastCrashDialog();
|
||||
} else {
|
||||
createRunningFile(runningPath);
|
||||
}
|
||||
|
||||
Application app(settings, paths);
|
||||
app.initialize(settings, paths);
|
||||
app.run(a);
|
||||
app.save();
|
||||
|
||||
removeRunningFile(runningPath);
|
||||
|
||||
pajlada::Settings::SettingManager::gSave();
|
||||
|
||||
chatterino::NetworkManager::deinit();
|
||||
|
||||
_exit(0);
|
||||
}
|
||||
} // namespace chatterino
|
10
src/RunGui.hpp
Normal file
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
class QApplication;
|
||||
|
||||
namespace chatterino {
|
||||
class Paths;
|
||||
class Settings;
|
||||
|
||||
void runGui(QApplication &a, Paths &paths, Settings &settings);
|
||||
} // namespace chatterino
|
44
src/autogenerated/ResourcesAutogen.cpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include "ResourcesAutogen.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
Resources2::Resources2()
|
||||
{
|
||||
this->avatars.fourtf = QPixmap(":/avatars/fourtf.png");
|
||||
this->avatars.pajlada = QPixmap(":/avatars/pajlada.png");
|
||||
this->buttons.ban = QPixmap(":/buttons/ban.png");
|
||||
this->buttons.banRed = QPixmap(":/buttons/banRed.png");
|
||||
this->buttons.menuDark = QPixmap(":/buttons/menuDark.png");
|
||||
this->buttons.menuLight = QPixmap(":/buttons/menuLight.png");
|
||||
this->buttons.mod = QPixmap(":/buttons/mod.png");
|
||||
this->buttons.modModeDisabled = QPixmap(":/buttons/modModeDisabled.png");
|
||||
this->buttons.modModeDisabled2 = QPixmap(":/buttons/modModeDisabled2.png");
|
||||
this->buttons.modModeEnabled = QPixmap(":/buttons/modModeEnabled.png");
|
||||
this->buttons.modModeEnabled2 = QPixmap(":/buttons/modModeEnabled2.png");
|
||||
this->buttons.timeout = QPixmap(":/buttons/timeout.png");
|
||||
this->buttons.unban = QPixmap(":/buttons/unban.png");
|
||||
this->buttons.unmod = QPixmap(":/buttons/unmod.png");
|
||||
this->buttons.update = QPixmap(":/buttons/update.png");
|
||||
this->buttons.updateError = QPixmap(":/buttons/updateError.png");
|
||||
this->error = QPixmap(":/error.png");
|
||||
this->icon = QPixmap(":/icon.png");
|
||||
this->pajaDank = QPixmap(":/pajaDank.png");
|
||||
this->settings.aboutlogo = QPixmap(":/settings/aboutlogo.png");
|
||||
this->split.down = QPixmap(":/split/down.png");
|
||||
this->split.left = QPixmap(":/split/left.png");
|
||||
this->split.move = QPixmap(":/split/move.png");
|
||||
this->split.right = QPixmap(":/split/right.png");
|
||||
this->split.up = QPixmap(":/split/up.png");
|
||||
this->twitch.admin = QPixmap(":/twitch/admin.png");
|
||||
this->twitch.broadcaster = QPixmap(":/twitch/broadcaster.png");
|
||||
this->twitch.cheer1 = QPixmap(":/twitch/cheer1.png");
|
||||
this->twitch.globalmod = QPixmap(":/twitch/globalmod.png");
|
||||
this->twitch.moderator = QPixmap(":/twitch/moderator.png");
|
||||
this->twitch.prime = QPixmap(":/twitch/prime.png");
|
||||
this->twitch.staff = QPixmap(":/twitch/staff.png");
|
||||
this->twitch.subscriber = QPixmap(":/twitch/subscriber.png");
|
||||
this->twitch.turbo = QPixmap(":/twitch/turbo.png");
|
||||
this->twitch.verified = QPixmap(":/twitch/verified.png");
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
57
src/autogenerated/ResourcesAutogen.hpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
#include <QPixmap>
|
||||
#include "common/Singleton.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class Resources2 : public Singleton {
|
||||
public:
|
||||
Resources2();
|
||||
|
||||
struct {
|
||||
QPixmap fourtf;
|
||||
QPixmap pajlada;
|
||||
} avatars;
|
||||
struct {
|
||||
QPixmap ban;
|
||||
QPixmap banRed;
|
||||
QPixmap menuDark;
|
||||
QPixmap menuLight;
|
||||
QPixmap mod;
|
||||
QPixmap modModeDisabled;
|
||||
QPixmap modModeDisabled2;
|
||||
QPixmap modModeEnabled;
|
||||
QPixmap modModeEnabled2;
|
||||
QPixmap timeout;
|
||||
QPixmap unban;
|
||||
QPixmap unmod;
|
||||
QPixmap update;
|
||||
QPixmap updateError;
|
||||
} buttons;
|
||||
QPixmap error;
|
||||
QPixmap icon;
|
||||
QPixmap pajaDank;
|
||||
struct {
|
||||
QPixmap aboutlogo;
|
||||
} settings;
|
||||
struct {
|
||||
QPixmap down;
|
||||
QPixmap left;
|
||||
QPixmap move;
|
||||
QPixmap right;
|
||||
QPixmap up;
|
||||
} split;
|
||||
struct {
|
||||
QPixmap admin;
|
||||
QPixmap broadcaster;
|
||||
QPixmap cheer1;
|
||||
QPixmap globalmod;
|
||||
QPixmap moderator;
|
||||
QPixmap prime;
|
||||
QPixmap staff;
|
||||
QPixmap subscriber;
|
||||
QPixmap turbo;
|
||||
QPixmap verified;
|
||||
} twitch;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
34
src/common/Aliases.hpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
#include <functional>
|
||||
|
||||
#define QStringAlias(name) \
|
||||
namespace chatterino { \
|
||||
struct name { \
|
||||
QString string; \
|
||||
bool operator==(const name &other) const \
|
||||
{ \
|
||||
return this->string == other.string; \
|
||||
} \
|
||||
bool operator!=(const name &other) const \
|
||||
{ \
|
||||
return this->string != other.string; \
|
||||
} \
|
||||
}; \
|
||||
} /* namespace chatterino */ \
|
||||
namespace std { \
|
||||
template <> \
|
||||
struct hash<chatterino::name> { \
|
||||
size_t operator()(const chatterino::name &s) const \
|
||||
{ \
|
||||
return qHash(s.string); \
|
||||
} \
|
||||
}; \
|
||||
} /* namespace std */
|
||||
|
||||
QStringAlias(UserName);
|
||||
QStringAlias(UserId);
|
||||
QStringAlias(Url);
|
||||
QStringAlias(Tooltip);
|
|
@ -17,9 +17,9 @@
|
|||
|
||||
namespace chatterino {
|
||||
|
||||
Channel::Channel(const QString &_name, Type type)
|
||||
: name(_name)
|
||||
, completionModel(this->name)
|
||||
Channel::Channel(const QString &name, Type type)
|
||||
: completionModel(name)
|
||||
, name_(name)
|
||||
, type_(type)
|
||||
{
|
||||
QObject::connect(&this->clearCompletionModelTimer_, &QTimer::timeout, [this]() {
|
||||
|
@ -38,6 +38,11 @@ Channel::Type Channel::getType() const
|
|||
return this->type_;
|
||||
}
|
||||
|
||||
const QString &Channel::getName() const
|
||||
{
|
||||
return this->name_;
|
||||
}
|
||||
|
||||
bool Channel::isTwitchChannel() const
|
||||
{
|
||||
return this->type_ >= Type::Twitch && this->type_ < Type::TwitchEnd;
|
||||
|
@ -45,7 +50,7 @@ bool Channel::isTwitchChannel() const
|
|||
|
||||
bool Channel::isEmpty() const
|
||||
{
|
||||
return this->name.isEmpty();
|
||||
return this->name_.isEmpty();
|
||||
}
|
||||
|
||||
LimitedQueueSnapshot<MessagePtr> Channel::getMessageSnapshot()
|
||||
|
@ -66,7 +71,7 @@ void Channel::addMessage(MessagePtr message)
|
|||
|
||||
// FOURTF: change this when adding more providers
|
||||
if (this->isTwitchChannel()) {
|
||||
app->logging->addMessage(this->name, message);
|
||||
app->logging->addMessage(this->name_, message);
|
||||
}
|
||||
|
||||
if (this->messages_.pushBack(message, deleted)) {
|
||||
|
|
|
@ -41,6 +41,7 @@ public:
|
|||
pajlada::Signals::NoArgSignal destroyed;
|
||||
|
||||
Type getType() const;
|
||||
const QString &getName() const;
|
||||
bool isTwitchChannel() const;
|
||||
virtual bool isEmpty() const;
|
||||
LimitedQueueSnapshot<MessagePtr> getMessageSnapshot();
|
||||
|
@ -52,7 +53,6 @@ public:
|
|||
void replaceMessage(MessagePtr message, MessagePtr replacement);
|
||||
virtual void addRecentChatter(const std::shared_ptr<Message> &message);
|
||||
|
||||
QString name;
|
||||
QStringList modList;
|
||||
|
||||
virtual bool canSendMessage() const;
|
||||
|
@ -72,6 +72,7 @@ protected:
|
|||
virtual void onConnected();
|
||||
|
||||
private:
|
||||
const QString name_;
|
||||
LimitedQueue<MessagePtr> messages_;
|
||||
Type type_;
|
||||
QTimer clearCompletionModelTimer_;
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "common/Aliases.hpp"
|
||||
#include "common/Outcome.hpp"
|
||||
#include "common/ProviderId.hpp"
|
||||
#include "debug/Log.hpp"
|
||||
|
||||
#include <QString>
|
||||
#include <QWidget>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/preprocessor.hpp>
|
||||
|
||||
#include <string>
|
||||
|
@ -27,14 +31,10 @@ const Qt::KeyboardModifiers showResizeHandlesModifiers = Qt::ControlModifier;
|
|||
|
||||
static const char *ANONYMOUS_USERNAME_LABEL ATTR_UNUSED = " - anonymous - ";
|
||||
|
||||
#define return_if(condition) \
|
||||
if ((condition)) { \
|
||||
return; \
|
||||
}
|
||||
|
||||
#define return_unless(condition) \
|
||||
if (!(condition)) { \
|
||||
return; \
|
||||
}
|
||||
template <typename T>
|
||||
std::weak_ptr<T> weakOf(T *element)
|
||||
{
|
||||
return element->shared_from_this();
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
#include "Application.hpp"
|
||||
#include "common/Common.hpp"
|
||||
#include "controllers/accounts/AccountController.hpp"
|
||||
#include "controllers/commands/CommandController.hpp"
|
||||
#include "debug/Log.hpp"
|
||||
#include "providers/twitch/TwitchServer.hpp"
|
||||
#include "singletons/Emotes.hpp"
|
||||
|
||||
#include <QtAlgorithms>
|
||||
|
@ -107,41 +109,45 @@ void CompletionModel::refresh()
|
|||
auto app = getApp();
|
||||
|
||||
// User-specific: Twitch Emotes
|
||||
// TODO: Fix this so it properly updates with the proper api. oauth token needs proper scope
|
||||
for (const auto &m : app->emotes->twitch.emotes) {
|
||||
for (const auto &emoteName : m.second.emoteCodes) {
|
||||
if (auto account = app->accounts->twitch.getCurrent()) {
|
||||
for (const auto &emote : account->accessEmotes()->allEmoteNames) {
|
||||
// XXX: No way to discern between a twitch global emote and sub emote right now
|
||||
this->addString(emoteName, TaggedString::Type::TwitchGlobalEmote);
|
||||
this->addString(emote.string, TaggedString::Type::TwitchGlobalEmote);
|
||||
}
|
||||
}
|
||||
|
||||
// Global: BTTV Global Emotes
|
||||
std::vector<QString> &bttvGlobalEmoteCodes = app->emotes->bttv.globalEmoteCodes;
|
||||
for (const auto &m : bttvGlobalEmoteCodes) {
|
||||
this->addString(m, TaggedString::Type::BTTVGlobalEmote);
|
||||
}
|
||||
// // Global: BTTV Global Emotes
|
||||
// std::vector<QString> &bttvGlobalEmoteCodes = app->emotes->bttv.globalEmoteNames_;
|
||||
// for (const auto &m : bttvGlobalEmoteCodes) {
|
||||
// this->addString(m, TaggedString::Type::BTTVGlobalEmote);
|
||||
// }
|
||||
|
||||
// Global: FFZ Global Emotes
|
||||
std::vector<QString> &ffzGlobalEmoteCodes = app->emotes->ffz.globalEmoteCodes;
|
||||
for (const auto &m : ffzGlobalEmoteCodes) {
|
||||
this->addString(m, TaggedString::Type::FFZGlobalEmote);
|
||||
}
|
||||
// // Global: FFZ Global Emotes
|
||||
// std::vector<QString> &ffzGlobalEmoteCodes = app->emotes->ffz.globalEmoteCodes;
|
||||
// for (const auto &m : ffzGlobalEmoteCodes) {
|
||||
// this->addString(m, TaggedString::Type::FFZGlobalEmote);
|
||||
// }
|
||||
|
||||
// Channel-specific: BTTV Channel Emotes
|
||||
std::vector<QString> &bttvChannelEmoteCodes =
|
||||
app->emotes->bttv.channelEmoteCodes[this->channelName_];
|
||||
for (const auto &m : bttvChannelEmoteCodes) {
|
||||
this->addString(m, TaggedString::Type::BTTVChannelEmote);
|
||||
}
|
||||
// Channel emotes
|
||||
if (auto channel = dynamic_cast<TwitchChannel *>(
|
||||
getApp()->twitch2->getChannelOrEmptyByID(this->channelName_).get())) {
|
||||
auto bttv = channel->accessBttvEmotes();
|
||||
// auto it = bttv->begin();
|
||||
// for (const auto &emote : *bttv) {
|
||||
// }
|
||||
// std::vector<QString> &bttvChannelEmoteCodes =
|
||||
// app->emotes->bttv.channelEmoteName_[this->channelName_];
|
||||
// for (const auto &m : bttvChannelEmoteCodes) {
|
||||
// this->addString(m, TaggedString::Type::BTTVChannelEmote);
|
||||
// }
|
||||
|
||||
// Channel-specific: FFZ Channel Emotes
|
||||
std::vector<QString> &ffzChannelEmoteCodes =
|
||||
app->emotes->ffz.channelEmoteCodes[this->channelName_];
|
||||
for (const auto &m : ffzChannelEmoteCodes) {
|
||||
this->addString(m, TaggedString::Type::FFZChannelEmote);
|
||||
for (const auto &emote : *channel->accessFfzEmotes()) {
|
||||
this->addString(emote.second->name.string, TaggedString::Type::FFZChannelEmote);
|
||||
}
|
||||
}
|
||||
|
||||
// Global: Emojis
|
||||
// Emojis
|
||||
const auto &emojiShortCodes = app->emotes->emojis.shortCodes;
|
||||
for (const auto &m : emojiShortCodes) {
|
||||
this->addString(":" + m + ":", TaggedString::Type::Emoji);
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
namespace chatterino {
|
||||
|
||||
class TwitchChannel;
|
||||
|
||||
class CompletionModel : public QAbstractListModel
|
||||
{
|
||||
struct TaggedString {
|
||||
|
|
|
@ -5,42 +5,42 @@
|
|||
|
||||
namespace chatterino {
|
||||
|
||||
EmoteData::EmoteData(Image *image)
|
||||
: image1x(image)
|
||||
{
|
||||
}
|
||||
// EmoteData::EmoteData(Image *image)
|
||||
// : image1x(image)
|
||||
//{
|
||||
//}
|
||||
|
||||
// Emotes must have a 1x image to be valid
|
||||
bool EmoteData::isValid() const
|
||||
{
|
||||
return this->image1x != nullptr;
|
||||
}
|
||||
//// Emotes must have a 1x image to be valid
|
||||
// bool EmoteData::isValid() const
|
||||
//{
|
||||
// return this->image1x != nullptr;
|
||||
//}
|
||||
|
||||
Image *EmoteData::getImage(float scale) const
|
||||
{
|
||||
int quality = getApp()->settings->preferredEmoteQuality;
|
||||
// Image *EmoteData::getImage(float scale) const
|
||||
//{
|
||||
// int quality = getApp()->settings->preferredEmoteQuality;
|
||||
|
||||
if (quality == 0) {
|
||||
scale *= getApp()->settings->emoteScale.getValue();
|
||||
quality = [&] {
|
||||
if (scale <= 1)
|
||||
return 1;
|
||||
if (scale <= 2)
|
||||
return 2;
|
||||
return 3;
|
||||
}();
|
||||
}
|
||||
// if (quality == 0) {
|
||||
// scale *= getApp()->settings->emoteScale.getValue();
|
||||
// quality = [&] {
|
||||
// if (scale <= 1)
|
||||
// return 1;
|
||||
// if (scale <= 2)
|
||||
// return 2;
|
||||
// return 3;
|
||||
// }();
|
||||
// }
|
||||
|
||||
Image *_image;
|
||||
if (quality == 3 && this->image3x != nullptr) {
|
||||
_image = this->image3x;
|
||||
} else if (quality >= 2 && this->image2x != nullptr) {
|
||||
_image = this->image2x;
|
||||
} else {
|
||||
_image = this->image1x;
|
||||
}
|
||||
// Image *_image;
|
||||
// if (quality == 3 && this->image3x != nullptr) {
|
||||
// _image = this->image3x;
|
||||
// } else if (quality >= 2 && this->image2x != nullptr) {
|
||||
// _image = this->image2x;
|
||||
// } else {
|
||||
// _image = this->image1x;
|
||||
// }
|
||||
|
||||
return _image;
|
||||
}
|
||||
// return _image;
|
||||
//}
|
||||
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -5,23 +5,23 @@
|
|||
|
||||
namespace chatterino {
|
||||
|
||||
struct EmoteData {
|
||||
EmoteData() = default;
|
||||
// struct EmoteData {
|
||||
// EmoteData() = default;
|
||||
|
||||
EmoteData(Image *image);
|
||||
// EmoteData(Image *image);
|
||||
|
||||
// Emotes must have a 1x image to be valid
|
||||
bool isValid() const;
|
||||
Image *getImage(float scale) const;
|
||||
// // Emotes must have a 1x image to be valid
|
||||
// bool isValid() const;
|
||||
// Image *getImage(float scale) const;
|
||||
|
||||
// Link to the emote page i.e. https://www.frankerfacez.com/emoticon/144722-pajaCringe
|
||||
QString pageLink;
|
||||
// // Link to the emote page i.e. https://www.frankerfacez.com/emoticon/144722-pajaCringe
|
||||
// QString pageLink;
|
||||
|
||||
Image *image1x = nullptr;
|
||||
Image *image2x = nullptr;
|
||||
Image *image3x = nullptr;
|
||||
};
|
||||
// Image *image1x = nullptr;
|
||||
// Image *image2x = nullptr;
|
||||
// Image *image3x = nullptr;
|
||||
//};
|
||||
|
||||
using EmoteMap = ConcurrentMap<QString, EmoteData>;
|
||||
// using EmoteMap = ConcurrentMap<QString, EmoteData>;
|
||||
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
|
||||
#include <functional>
|
||||
|
||||
#include "Common.hpp"
|
||||
|
||||
class QNetworkReply;
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class NetworkResult;
|
||||
|
||||
using NetworkSuccessCallback = std::function<bool(NetworkResult)>;
|
||||
using NetworkSuccessCallback = std::function<Outcome(NetworkResult)>;
|
||||
using NetworkErrorCallback = std::function<bool(int)>;
|
||||
using NetworkReplyCreatedCallback = std::function<void(QNetworkReply *)>;
|
||||
|
||||
|
|
|
@ -2,12 +2,23 @@
|
|||
|
||||
#include "Application.hpp"
|
||||
#include "singletons/Paths.hpp"
|
||||
#include "util/DebugCount.hpp"
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QFile>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
NetworkData::NetworkData()
|
||||
{
|
||||
DebugCount::increase("NetworkData");
|
||||
}
|
||||
|
||||
NetworkData::~NetworkData()
|
||||
{
|
||||
DebugCount::decrease("NetworkData");
|
||||
}
|
||||
|
||||
QString NetworkData::getHash()
|
||||
{
|
||||
if (this->hash_.isEmpty()) {
|
||||
|
|
|
@ -13,6 +13,9 @@ namespace chatterino {
|
|||
class NetworkResult;
|
||||
|
||||
struct NetworkData {
|
||||
NetworkData();
|
||||
~NetworkData();
|
||||
|
||||
QNetworkRequest request_;
|
||||
const QObject *caller_ = nullptr;
|
||||
bool useQuickLoadCache_{};
|
||||
|
|
|
@ -129,7 +129,7 @@ void NetworkRequest::execute()
|
|||
}
|
||||
}
|
||||
|
||||
bool NetworkRequest::tryLoadCachedFile()
|
||||
Outcome NetworkRequest::tryLoadCachedFile()
|
||||
{
|
||||
auto app = getApp();
|
||||
|
||||
|
@ -137,24 +137,24 @@ bool NetworkRequest::tryLoadCachedFile()
|
|||
|
||||
if (!cachedFile.exists()) {
|
||||
// File didn't exist
|
||||
return false;
|
||||
return Failure;
|
||||
}
|
||||
|
||||
if (!cachedFile.open(QIODevice::ReadOnly)) {
|
||||
// File could not be opened
|
||||
return false;
|
||||
return Failure;
|
||||
}
|
||||
|
||||
QByteArray bytes = cachedFile.readAll();
|
||||
NetworkResult result(bytes);
|
||||
|
||||
bool success = this->data->onSuccess_(result);
|
||||
auto outcome = this->data->onSuccess_(result);
|
||||
|
||||
cachedFile.close();
|
||||
|
||||
// XXX: If success is false, we should invalidate the cache file somehow/somewhere
|
||||
|
||||
return success;
|
||||
return outcome;
|
||||
}
|
||||
|
||||
void NetworkRequest::doRequest()
|
||||
|
@ -167,20 +167,21 @@ void NetworkRequest::doRequest()
|
|||
this->timer->start();
|
||||
|
||||
auto onUrlRequested = [data = this->data, timer = this->timer, worker]() mutable {
|
||||
QNetworkReply *reply = nullptr;
|
||||
auto reply = [&]() -> QNetworkReply * {
|
||||
switch (data->requestType_) {
|
||||
case NetworkRequestType::Get: {
|
||||
reply = NetworkManager::NaM.get(data->request_);
|
||||
} break;
|
||||
case NetworkRequestType::Get:
|
||||
return NetworkManager::NaM.get(data->request_);
|
||||
|
||||
case NetworkRequestType::Put: {
|
||||
reply = NetworkManager::NaM.put(data->request_, data->payload_);
|
||||
} break;
|
||||
case NetworkRequestType::Put:
|
||||
return NetworkManager::NaM.put(data->request_, data->payload_);
|
||||
|
||||
case NetworkRequestType::Delete: {
|
||||
reply = NetworkManager::NaM.deleteResource(data->request_);
|
||||
} break;
|
||||
case NetworkRequestType::Delete:
|
||||
return NetworkManager::NaM.deleteResource(data->request_);
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}();
|
||||
|
||||
if (reply == nullptr) {
|
||||
Log("Unhandled request type");
|
||||
|
@ -201,8 +202,6 @@ void NetworkRequest::doRequest()
|
|||
data->onReplyCreated_(reply);
|
||||
}
|
||||
|
||||
bool directAction = (data->caller_ == nullptr);
|
||||
|
||||
auto handleReply = [data, timer, reply]() mutable {
|
||||
// TODO(pajlada): A reply was received, kill the timeout timer
|
||||
if (reply->error() != QNetworkReply::NetworkError::NoError) {
|
||||
|
@ -222,8 +221,7 @@ void NetworkRequest::doRequest()
|
|||
};
|
||||
|
||||
if (data->caller_ != nullptr) {
|
||||
QObject::connect(worker, &NetworkWorker::doneUrl, data->caller_,
|
||||
std::move(handleReply));
|
||||
QObject::connect(worker, &NetworkWorker::doneUrl, data->caller_, handleReply);
|
||||
QObject::connect(reply, &QNetworkReply::finished, worker, [worker]() mutable {
|
||||
emit worker->doneUrl();
|
||||
|
||||
|
@ -231,7 +229,7 @@ void NetworkRequest::doRequest()
|
|||
});
|
||||
} else {
|
||||
QObject::connect(reply, &QNetworkReply::finished, worker,
|
||||
[handleReply = std::move(handleReply), worker]() mutable {
|
||||
[handleReply, worker]() mutable {
|
||||
handleReply();
|
||||
|
||||
delete worker;
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
|
||||
explicit NetworkRequest(const std::string &url,
|
||||
NetworkRequestType requestType = NetworkRequestType::Get);
|
||||
NetworkRequest(QUrl url, NetworkRequestType requestType = NetworkRequestType::Get);
|
||||
explicit NetworkRequest(QUrl url, NetworkRequestType requestType = NetworkRequestType::Get);
|
||||
|
||||
~NetworkRequest();
|
||||
|
||||
|
@ -58,7 +58,7 @@ private:
|
|||
// Returns true if the file was successfully loaded from cache
|
||||
// Returns false if the cache file either didn't exist, or it contained "invalid" data
|
||||
// "invalid" is specified by the onSuccess callback
|
||||
bool tryLoadCachedFile();
|
||||
Outcome tryLoadCachedFile();
|
||||
|
||||
void doRequest();
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ rapidjson::Document NetworkResult::parseRapidJson() const
|
|||
return ret;
|
||||
}
|
||||
|
||||
QByteArray NetworkResult::getData() const
|
||||
const QByteArray &NetworkResult::getData() const
|
||||
{
|
||||
return this->data_;
|
||||
}
|
||||
|
|
|
@ -7,14 +7,15 @@ namespace chatterino {
|
|||
|
||||
class NetworkResult
|
||||
{
|
||||
QByteArray data_;
|
||||
|
||||
public:
|
||||
NetworkResult(const QByteArray &data);
|
||||
|
||||
QJsonObject parseJson() const;
|
||||
rapidjson::Document parseRapidJson() const;
|
||||
QByteArray getData() const;
|
||||
const QByteArray &getData() const;
|
||||
|
||||
private:
|
||||
QByteArray data_;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
template <typename T>
|
||||
|
@ -23,7 +25,7 @@ public:
|
|||
return element_;
|
||||
}
|
||||
|
||||
T &operator*() const
|
||||
typename std::add_lvalue_reference<T>::type operator*() const
|
||||
{
|
||||
assert(this->hasElement());
|
||||
|
||||
|
@ -52,6 +54,17 @@ public:
|
|||
return this->hasElement();
|
||||
}
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return !this->hasElement();
|
||||
}
|
||||
|
||||
template <typename X = T, typename = std::enable_if_t<!std::is_const<X>::value>>
|
||||
operator NullablePtr<const T>() const
|
||||
{
|
||||
return NullablePtr<const T>(this->element_);
|
||||
}
|
||||
|
||||
private:
|
||||
T *element_;
|
||||
};
|
||||
|
|
51
src/common/Outcome.hpp
Normal file
|
@ -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
|
|
@ -4,14 +4,18 @@
|
|||
|
||||
namespace chatterino {
|
||||
|
||||
class Application;
|
||||
class Settings;
|
||||
class Paths;
|
||||
|
||||
class Singleton : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
virtual void initialize(Application &app)
|
||||
virtual ~Singleton() = default;
|
||||
|
||||
virtual void initialize(Settings &settings, Paths &paths)
|
||||
{
|
||||
(void)(app);
|
||||
(void)(settings);
|
||||
(void)(paths);
|
||||
}
|
||||
|
||||
virtual void save()
|
||||
|
|
|
@ -10,52 +10,52 @@ class AccessGuard
|
|||
{
|
||||
public:
|
||||
AccessGuard(T &element, std::mutex &mutex)
|
||||
: element_(element)
|
||||
, mutex_(mutex)
|
||||
: element_(&element)
|
||||
, mutex_(&mutex)
|
||||
{
|
||||
this->mutex_.lock();
|
||||
this->mutex_->lock();
|
||||
}
|
||||
|
||||
AccessGuard(AccessGuard<T> &&other)
|
||||
: element_(other.element_)
|
||||
, mutex_(other.mutex_)
|
||||
{
|
||||
other.isValid_ = false;
|
||||
}
|
||||
|
||||
AccessGuard<T> &operator=(AccessGuard<T> &&other)
|
||||
{
|
||||
other.isValid_ = false;
|
||||
this->element_ = other.element_;
|
||||
this->mutex_ = other.element_;
|
||||
}
|
||||
|
||||
~AccessGuard()
|
||||
{
|
||||
this->mutex_.unlock();
|
||||
if (this->isValid_) this->mutex_->unlock();
|
||||
}
|
||||
|
||||
const T *operator->() const
|
||||
{
|
||||
return &this->element_;
|
||||
}
|
||||
|
||||
T *operator->()
|
||||
{
|
||||
return &this->element_;
|
||||
}
|
||||
|
||||
const T &operator*() const
|
||||
T *operator->() const
|
||||
{
|
||||
return this->element_;
|
||||
}
|
||||
|
||||
T &operator*()
|
||||
T &operator*() const
|
||||
{
|
||||
return this->element_;
|
||||
}
|
||||
|
||||
T clone() const
|
||||
{
|
||||
return T(this->element_);
|
||||
return *this->element_;
|
||||
}
|
||||
|
||||
private:
|
||||
T &element_;
|
||||
std::mutex &mutex_;
|
||||
T *element_;
|
||||
std::mutex *mutex_;
|
||||
bool isValid_ = true;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class UniqueAccess
|
||||
{
|
||||
public:
|
||||
template <typename X = decltype(T())>
|
||||
// template <typename X = decltype(T())>
|
||||
UniqueAccess()
|
||||
: element_(T())
|
||||
{
|
||||
|
@ -83,14 +83,15 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
AccessGuard<T> access()
|
||||
AccessGuard<T> access() const
|
||||
{
|
||||
return AccessGuard<T>(this->element_, this->mutex_);
|
||||
}
|
||||
|
||||
const AccessGuard<T> access() const
|
||||
template <typename X = T, typename = std::enable_if_t<!std::is_const_v<X>>>
|
||||
AccessGuard<const X> accessConst() const
|
||||
{
|
||||
return AccessGuard<T>(this->element_, this->mutex_);
|
||||
return AccessGuard<const T>(this->element_, this->mutex_);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -33,7 +33,7 @@ AccountController::AccountController()
|
|||
});
|
||||
}
|
||||
|
||||
void AccountController::initialize(Application &app)
|
||||
void AccountController::initialize(Settings &settings, Paths &paths)
|
||||
{
|
||||
this->twitch.load();
|
||||
}
|
||||
|
|
|
@ -11,16 +11,19 @@
|
|||
|
||||
namespace chatterino {
|
||||
|
||||
class Settings;
|
||||
class Paths;
|
||||
|
||||
class AccountModel;
|
||||
|
||||
class AccountController : public Singleton
|
||||
class AccountController final : public Singleton
|
||||
{
|
||||
public:
|
||||
AccountController();
|
||||
|
||||
AccountModel *createModel(QObject *parent);
|
||||
|
||||
virtual void initialize(Application &app) override;
|
||||
virtual void initialize(Settings &settings, Paths &paths) override;
|
||||
|
||||
TwitchAccountManager twitch;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "providers/twitch/TwitchServer.hpp"
|
||||
#include "singletons/Paths.hpp"
|
||||
#include "singletons/Settings.hpp"
|
||||
#include "util/CombinePath.hpp"
|
||||
#include "widgets/dialogs/LogsPopup.hpp"
|
||||
|
||||
#include <QApplication>
|
||||
|
@ -44,15 +45,14 @@ CommandController::CommandController()
|
|||
this->items.itemRemoved.connect(addFirstMatchToMap);
|
||||
}
|
||||
|
||||
void CommandController::initialize(Application &app)
|
||||
void CommandController::initialize(Settings &, Paths &paths)
|
||||
{
|
||||
this->load();
|
||||
this->load(paths);
|
||||
}
|
||||
|
||||
void CommandController::load()
|
||||
void CommandController::load(Paths &paths)
|
||||
{
|
||||
auto app = getApp();
|
||||
this->filePath_ = app->paths->settingsDirectory + "/commands.txt";
|
||||
this->filePath_ = combinePath(paths.settingsDirectory, "commands.txt");
|
||||
|
||||
QFile textFile(this->filePath_);
|
||||
if (!textFile.open(QIODevice::ReadOnly)) {
|
||||
|
@ -140,7 +140,7 @@ QString CommandController::execCommand(const QString &text, ChannelPtr channel,
|
|||
|
||||
app->twitch.server->whispersChannel->addMessage(b.getMessage());
|
||||
|
||||
app->twitch.server->getWriteConnection()->sendRaw("PRIVMSG #jtv :" + text + "\r\n");
|
||||
app->twitch.server->sendMessage("jtv", text);
|
||||
|
||||
if (getSettings()->inlineWhispers) {
|
||||
app->twitch.server->forEachChannel(
|
||||
|
|
|
@ -10,11 +10,14 @@
|
|||
#include "controllers/commands/Command.hpp"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
class Settings;
|
||||
class Paths;
|
||||
class Channel;
|
||||
|
||||
class CommandModel;
|
||||
|
||||
class CommandController : public Singleton
|
||||
class CommandController final : public Singleton
|
||||
{
|
||||
public:
|
||||
CommandController();
|
||||
|
@ -22,7 +25,7 @@ public:
|
|||
QString execCommand(const QString &text, std::shared_ptr<Channel> channel, bool dryRun);
|
||||
QStringList getDefaultTwitchCommandList();
|
||||
|
||||
virtual void initialize(Application &app) override;
|
||||
virtual void initialize(Settings &settings, Paths &paths) override;
|
||||
virtual void save() override;
|
||||
|
||||
CommandModel *createModel(QObject *parent);
|
||||
|
@ -30,7 +33,7 @@ public:
|
|||
UnsortedSignalVector<Command> items;
|
||||
|
||||
private:
|
||||
void load();
|
||||
void load(Paths &paths);
|
||||
|
||||
QMap<QString, Command> commandsMap_;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ HighlightController::HighlightController()
|
|||
{
|
||||
}
|
||||
|
||||
void HighlightController::initialize(Application &app)
|
||||
void HighlightController::initialize(Settings &settings, Paths &paths)
|
||||
{
|
||||
assert(!this->initialized_);
|
||||
this->initialized_ = true;
|
||||
|
|