Merge branch 'master' into irc-support
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
# Normalize line endings to LF for files that Git detects as text
|
||||||
|
* text=auto
|
||||||
+3
-4
@@ -4,10 +4,6 @@
|
|||||||
[submodule "lib/humanize"]
|
[submodule "lib/humanize"]
|
||||||
path = lib/humanize
|
path = lib/humanize
|
||||||
url = https://github.com/pajlada/humanize.git
|
url = https://github.com/pajlada/humanize.git
|
||||||
[submodule "lib/websocketpp"]
|
|
||||||
path = lib/websocketpp
|
|
||||||
url = https://github.com/zaphoyd/websocketpp.git
|
|
||||||
branch = develop
|
|
||||||
[submodule "lib/qBreakpad"]
|
[submodule "lib/qBreakpad"]
|
||||||
path = lib/qBreakpad
|
path = lib/qBreakpad
|
||||||
url = https://github.com/jiakuan/qBreakpad.git
|
url = https://github.com/jiakuan/qBreakpad.git
|
||||||
@@ -29,3 +25,6 @@
|
|||||||
[submodule "lib/qtkeychain"]
|
[submodule "lib/qtkeychain"]
|
||||||
path = lib/qtkeychain
|
path = lib/qtkeychain
|
||||||
url = https://github.com/Chatterino/qtkeychain
|
url = https://github.com/Chatterino/qtkeychain
|
||||||
|
[submodule "lib/websocketpp"]
|
||||||
|
path = lib/websocketpp
|
||||||
|
url = https://github.com/ziocleto/websocketpp
|
||||||
|
|||||||
+61
-59
@@ -1,59 +1,61 @@
|
|||||||
version: "{build}"
|
version: "{build}"
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
image: Visual Studio 2017
|
image: Visual Studio 2017
|
||||||
platform: Any CPU
|
platform: Any CPU
|
||||||
clone_depth: 1
|
clone_depth: 1
|
||||||
init:
|
init:
|
||||||
- cmd: ''
|
- cmd: ''
|
||||||
install:
|
install:
|
||||||
- cmd: >-
|
- cmd: >-
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
|
|
||||||
set QTDIR=C:\Qt\5.11\msvc2017_64
|
set QTDIR=C:\Qt\5.11\msvc2017_64
|
||||||
|
|
||||||
set PATH=%PATH%;%QTDIR%\bin
|
set PATH=%PATH%;%QTDIR%\bin
|
||||||
|
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
|
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||||
|
|
||||||
pip install conan -q
|
pip install conan -q
|
||||||
build_script:
|
build_script:
|
||||||
- cmd: >-
|
- cmd: >-
|
||||||
dir
|
dir
|
||||||
|
|
||||||
mkdir build
|
mkdir build
|
||||||
|
|
||||||
cd build
|
cd build
|
||||||
|
|
||||||
conan install ..
|
conan install ..
|
||||||
|
|
||||||
set dateOfBuild=%date:~7,2%.%date:~4,2%.%date:~10,4%
|
set dateOfBuild=%date:~7,2%.%date:~4,2%.%date:~10,4%
|
||||||
|
|
||||||
qmake ../chatterino.pro DEFINES+="CHATTERINO_NIGHTLY_VERSION_STRING=\\\"'$s%dateOfBuild% '$$system(git describe --always)-$$system(git rev-list master --count)\\\""
|
qmake ../chatterino.pro DEFINES+="CHATTERINO_NIGHTLY_VERSION_STRING=\\\"'$s%dateOfBuild% '$$system(git describe --always)-$$system(git rev-list master --count)\\\""
|
||||||
|
|
||||||
set cl=/MP
|
set cl=/MP
|
||||||
|
|
||||||
nmake /S /NOLOGO
|
nmake /S /NOLOGO
|
||||||
|
|
||||||
windeployqt release/chatterino.exe --release --no-compiler-runtime --no-translations --no-opengl-sw --dir Chatterino2/
|
windeployqt release/chatterino.exe --release --no-compiler-runtime --no-translations --no-opengl-sw --dir Chatterino2/
|
||||||
|
|
||||||
cp release/chatterino.exe Chatterino2/
|
cp release/chatterino.exe Chatterino2/
|
||||||
|
|
||||||
7z a chatterino-windows-x86-64.zip Chatterino2/
|
echo nightly > Chatterino2/modes
|
||||||
artifacts:
|
|
||||||
- path: build/chatterino-windows-x86-64.zip
|
7z a chatterino-windows-x86-64.zip Chatterino2/
|
||||||
name: chatterino
|
artifacts:
|
||||||
deploy:
|
- path: build/chatterino-windows-x86-64.zip
|
||||||
- provider: GitHub
|
name: chatterino
|
||||||
tag: nightly-build
|
deploy:
|
||||||
release: nightly-build
|
- provider: GitHub
|
||||||
description: 'nightly v$(appveyor_build_version) built $(APPVEYOR_REPO_COMMIT_TIMESTAMP)\nLast change: $(APPVEYOR_REPO_COMMIT_MESSAGE) \n$(APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED)'
|
tag: nightly-build
|
||||||
auth_token:
|
release: nightly-build
|
||||||
secure: sAJzAbiQSsYZLT+byDar9u61X0E9o35anaPMSFkOzdHeDFHjx1kW4cDP/4EEbxhx
|
description: 'nightly v$(appveyor_build_version) built 👉 $(APPVEYOR_REPO_COMMIT_TIMESTAMP) 👈\nLast change: $(APPVEYOR_REPO_COMMIT_MESSAGE) \n$(APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED)'
|
||||||
repository: Chatterino/chatterino2
|
auth_token:
|
||||||
artifact: build/chatterino-windows-x86-64.zip
|
secure: sAJzAbiQSsYZLT+byDar9u61X0E9o35anaPMSFkOzdHeDFHjx1kW4cDP/4EEbxhx
|
||||||
prerelease: true
|
repository: Chatterino/chatterino2
|
||||||
force_update: true
|
artifact: build/chatterino-windows-x86-64.zip
|
||||||
on:
|
prerelease: true
|
||||||
branch: master
|
force_update: true
|
||||||
|
on:
|
||||||
|
branch: master
|
||||||
|
|||||||
+470
-461
@@ -1,461 +1,470 @@
|
|||||||
QT += widgets core gui network multimedia svg concurrent
|
QT += widgets core gui network multimedia svg concurrent
|
||||||
CONFIG += communi
|
CONFIG += communi
|
||||||
COMMUNI += core model util
|
COMMUNI += core model util
|
||||||
|
|
||||||
INCLUDEPATH += src/
|
INCLUDEPATH += src/
|
||||||
TARGET = chatterino
|
TARGET = chatterino
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
PRECOMPILED_HEADER = src/PrecompiledHeader.hpp
|
PRECOMPILED_HEADER = src/PrecompiledHeader.hpp
|
||||||
CONFIG += precompile_header
|
CONFIG += precompile_header
|
||||||
DEFINES += CHATTERINO
|
DEFINES += CHATTERINO
|
||||||
DEFINES += "AB_NAMESPACE=chatterino"
|
DEFINES += "AB_NAMESPACE=chatterino"
|
||||||
DEFINES += AB_CUSTOM_THEME
|
DEFINES += AB_CUSTOM_THEME
|
||||||
DEFINES += AB_CUSTOM_SETTINGS
|
DEFINES += AB_CUSTOM_SETTINGS
|
||||||
CONFIG += AB_NOT_STANDALONE
|
CONFIG += AB_NOT_STANDALONE
|
||||||
|
|
||||||
useBreakpad {
|
useBreakpad {
|
||||||
LIBS += -L$$PWD/lib/qBreakpad/handler/build
|
LIBS += -L$$PWD/lib/qBreakpad/handler/build
|
||||||
include(lib/qBreakpad/qBreakpad.pri)
|
include(lib/qBreakpad/qBreakpad.pri)
|
||||||
DEFINES += C_USE_BREAKPAD
|
DEFINES += C_USE_BREAKPAD
|
||||||
}
|
}
|
||||||
|
|
||||||
# use C++17
|
# use C++17
|
||||||
win32-msvc* {
|
win32-msvc* {
|
||||||
QMAKE_CXXFLAGS += /std:c++17
|
QMAKE_CXXFLAGS += /std:c++17
|
||||||
} else {
|
} else {
|
||||||
QMAKE_CXXFLAGS += -std=c++17
|
QMAKE_CXXFLAGS += -std=c++17
|
||||||
}
|
}
|
||||||
|
|
||||||
# https://bugreports.qt.io/browse/QTBUG-27018
|
# https://bugreports.qt.io/browse/QTBUG-27018
|
||||||
equals(QMAKE_CXX, "clang++")|equals(QMAKE_CXX, "g++") {
|
equals(QMAKE_CXX, "clang++")|equals(QMAKE_CXX, "g++") {
|
||||||
TARGET = bin/chatterino
|
TARGET = bin/chatterino
|
||||||
}
|
}
|
||||||
|
|
||||||
# Icons
|
# Icons
|
||||||
macx:ICON = resources/chatterino.icns
|
macx:ICON = resources/chatterino.icns
|
||||||
win32:RC_FILE = resources/windows.rc
|
win32:RC_FILE = resources/windows.rc
|
||||||
|
|
||||||
macx {
|
macx {
|
||||||
LIBS += -L/usr/local/lib
|
LIBS += -L/usr/local/lib
|
||||||
}
|
}
|
||||||
|
|
||||||
# Submodules
|
# Submodules
|
||||||
include(lib/warnings.pri)
|
include(lib/warnings.pri)
|
||||||
include(lib/appbase.pri)
|
include(lib/appbase.pri)
|
||||||
include(lib/fmt.pri)
|
include(lib/fmt.pri)
|
||||||
include(lib/humanize.pri)
|
include(lib/humanize.pri)
|
||||||
include(lib/libcommuni.pri)
|
include(lib/libcommuni.pri)
|
||||||
include(lib/websocketpp.pri)
|
include(lib/websocketpp.pri)
|
||||||
include(lib/wintoast.pri)
|
include(lib/wintoast.pri)
|
||||||
include(lib/signals.pri)
|
include(lib/signals.pri)
|
||||||
include(lib/settings.pri)
|
include(lib/settings.pri)
|
||||||
include(lib/serialize.pri)
|
include(lib/serialize.pri)
|
||||||
include(lib/winsdk.pri)
|
include(lib/winsdk.pri)
|
||||||
include(lib/rapidjson.pri)
|
include(lib/rapidjson.pri)
|
||||||
include(lib/qtkeychain.pri)
|
include(lib/qtkeychain.pri)
|
||||||
|
|
||||||
exists( $$OUT_PWD/conanbuildinfo.pri ) {
|
exists( $$OUT_PWD/conanbuildinfo.pri ) {
|
||||||
message("Using conan packages")
|
message("Using conan packages")
|
||||||
CONFIG += conan_basic_setup
|
CONFIG += conan_basic_setup
|
||||||
include($$OUT_PWD/conanbuildinfo.pri)
|
include($$OUT_PWD/conanbuildinfo.pri)
|
||||||
LIBS += -lGdi32
|
LIBS += -lGdi32
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
include(lib/boost.pri)
|
include(lib/boost.pri)
|
||||||
include(lib/openssl.pri)
|
include(lib/openssl.pri)
|
||||||
}
|
}
|
||||||
|
|
||||||
# Optional feature: QtWebEngine
|
# Optional feature: QtWebEngine
|
||||||
#exists ($(QTDIR)/include/QtWebEngine/QtWebEngine) {
|
#exists ($(QTDIR)/include/QtWebEngine/QtWebEngine) {
|
||||||
# message(Using QWebEngine)
|
# message(Using QWebEngine)
|
||||||
# QT += webenginewidgets
|
# QT += webenginewidgets
|
||||||
# DEFINES += "USEWEBENGINE"
|
# DEFINES += "USEWEBENGINE"
|
||||||
#}
|
#}
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
src/Application.cpp \
|
src/Application.cpp \
|
||||||
src/autogenerated/ResourcesAutogen.cpp \
|
src/autogenerated/ResourcesAutogen.cpp \
|
||||||
src/BrowserExtension.cpp \
|
src/BrowserExtension.cpp \
|
||||||
src/common/Channel.cpp \
|
src/common/Channel.cpp \
|
||||||
src/common/ChannelChatters.cpp \
|
src/common/ChannelChatters.cpp \
|
||||||
src/common/CompletionModel.cpp \
|
src/common/CompletionModel.cpp \
|
||||||
src/common/Credentials.cpp \
|
src/common/Credentials.cpp \
|
||||||
src/common/DownloadManager.cpp \
|
src/common/DownloadManager.cpp \
|
||||||
src/common/Env.cpp \
|
src/common/Env.cpp \
|
||||||
src/common/LinkParser.cpp \
|
src/common/LinkParser.cpp \
|
||||||
src/common/NetworkManager.cpp \
|
src/common/Modes.cpp \
|
||||||
src/common/NetworkPrivate.cpp \
|
src/common/NetworkManager.cpp \
|
||||||
src/common/NetworkRequest.cpp \
|
src/common/NetworkPrivate.cpp \
|
||||||
src/common/NetworkResult.cpp \
|
src/common/NetworkRequest.cpp \
|
||||||
src/common/UsernameSet.cpp \
|
src/common/NetworkResult.cpp \
|
||||||
src/controllers/accounts/Account.cpp \
|
src/common/UsernameSet.cpp \
|
||||||
src/controllers/accounts/AccountController.cpp \
|
src/controllers/accounts/Account.cpp \
|
||||||
src/controllers/accounts/AccountModel.cpp \
|
src/controllers/accounts/AccountController.cpp \
|
||||||
src/controllers/commands/Command.cpp \
|
src/controllers/accounts/AccountModel.cpp \
|
||||||
src/controllers/commands/CommandController.cpp \
|
src/controllers/commands/Command.cpp \
|
||||||
src/controllers/commands/CommandModel.cpp \
|
src/controllers/commands/CommandController.cpp \
|
||||||
src/controllers/highlights/HighlightBlacklistModel.cpp \
|
src/controllers/commands/CommandModel.cpp \
|
||||||
src/controllers/highlights/HighlightController.cpp \
|
src/controllers/highlights/HighlightBlacklistModel.cpp \
|
||||||
src/controllers/highlights/HighlightModel.cpp \
|
src/controllers/highlights/HighlightController.cpp \
|
||||||
src/controllers/highlights/UserHighlightModel.cpp \
|
src/controllers/highlights/HighlightModel.cpp \
|
||||||
src/controllers/ignores/IgnoreController.cpp \
|
src/controllers/highlights/UserHighlightModel.cpp \
|
||||||
src/controllers/ignores/IgnoreModel.cpp \
|
src/controllers/ignores/IgnoreController.cpp \
|
||||||
src/controllers/moderationactions/ModerationAction.cpp \
|
src/controllers/ignores/IgnoreModel.cpp \
|
||||||
src/controllers/moderationactions/ModerationActionModel.cpp \
|
src/controllers/moderationactions/ModerationAction.cpp \
|
||||||
src/controllers/moderationactions/ModerationActions.cpp \
|
src/controllers/moderationactions/ModerationActionModel.cpp \
|
||||||
src/controllers/notifications/NotificationController.cpp \
|
src/controllers/moderationactions/ModerationActions.cpp \
|
||||||
src/controllers/notifications/NotificationModel.cpp \
|
src/controllers/notifications/NotificationController.cpp \
|
||||||
src/controllers/pings/PingController.cpp \
|
src/controllers/notifications/NotificationModel.cpp \
|
||||||
src/controllers/pings/PingModel.cpp \
|
src/controllers/pings/PingController.cpp \
|
||||||
src/controllers/taggedusers/TaggedUser.cpp \
|
src/controllers/pings/PingModel.cpp \
|
||||||
src/controllers/taggedusers/TaggedUsersController.cpp \
|
src/controllers/taggedusers/TaggedUser.cpp \
|
||||||
src/controllers/taggedusers/TaggedUsersModel.cpp \
|
src/controllers/taggedusers/TaggedUsersController.cpp \
|
||||||
src/main.cpp \
|
src/controllers/taggedusers/TaggedUsersModel.cpp \
|
||||||
src/messages/Emote.cpp \
|
src/main.cpp \
|
||||||
src/messages/Image.cpp \
|
src/messages/Emote.cpp \
|
||||||
src/messages/ImageSet.cpp \
|
src/messages/Image.cpp \
|
||||||
src/messages/layouts/MessageLayout.cpp \
|
src/messages/ImageSet.cpp \
|
||||||
src/messages/layouts/MessageLayoutContainer.cpp \
|
src/messages/layouts/MessageLayout.cpp \
|
||||||
src/messages/layouts/MessageLayoutElement.cpp \
|
src/messages/layouts/MessageLayoutContainer.cpp \
|
||||||
src/messages/Link.cpp \
|
src/messages/layouts/MessageLayoutElement.cpp \
|
||||||
src/messages/Message.cpp \
|
src/messages/Link.cpp \
|
||||||
src/messages/MessageBuilder.cpp \
|
src/messages/Message.cpp \
|
||||||
src/messages/MessageColor.cpp \
|
src/messages/MessageBuilder.cpp \
|
||||||
src/messages/MessageContainer.cpp \
|
src/messages/MessageColor.cpp \
|
||||||
src/messages/MessageElement.cpp \
|
src/messages/MessageContainer.cpp \
|
||||||
src/providers/bttv/BttvEmotes.cpp \
|
src/messages/MessageElement.cpp \
|
||||||
src/providers/bttv/LoadBttvChannelEmote.cpp \
|
src/messages/search/AuthorPredicate.cpp \
|
||||||
src/providers/chatterino/ChatterinoBadges.cpp \
|
src/messages/search/LinkPredicate.cpp \
|
||||||
src/providers/emoji/Emojis.cpp \
|
src/messages/search/SubstringPredicate.cpp \
|
||||||
src/providers/ffz/FfzEmotes.cpp \
|
src/providers/bttv/BttvEmotes.cpp \
|
||||||
src/providers/ffz/FfzModBadge.cpp \
|
src/providers/bttv/LoadBttvChannelEmote.cpp \
|
||||||
src/providers/irc/AbstractIrcServer.cpp \
|
src/providers/chatterino/ChatterinoBadges.cpp \
|
||||||
src/providers/irc/Irc2.cpp \
|
src/providers/emoji/Emojis.cpp \
|
||||||
src/providers/irc/IrcAccount.cpp \
|
src/providers/ffz/FfzEmotes.cpp \
|
||||||
src/providers/irc/IrcChannel2.cpp \
|
src/providers/irc/AbstractIrcServer.cpp \
|
||||||
src/providers/irc/IrcCommands.cpp \
|
src/providers/irc/Irc2.cpp \
|
||||||
src/providers/irc/IrcConnection2.cpp \
|
src/providers/irc/IrcAccount.cpp \
|
||||||
src/providers/irc/IrcServer.cpp \
|
src/providers/irc/IrcChannel2.cpp \
|
||||||
src/providers/LinkResolver.cpp \
|
src/providers/irc/IrcCommands.cpp \
|
||||||
src/providers/twitch/ChatroomChannel.cpp \
|
src/providers/irc/IrcConnection2.cpp \
|
||||||
src/providers/twitch/IrcMessageHandler.cpp \
|
src/providers/irc/IrcServer.cpp \
|
||||||
src/providers/twitch/PartialTwitchUser.cpp \
|
src/providers/LinkResolver.cpp \
|
||||||
src/providers/twitch/PubsubActions.cpp \
|
src/providers/twitch/ChatroomChannel.cpp \
|
||||||
src/providers/twitch/PubsubClient.cpp \
|
src/providers/twitch/IrcMessageHandler.cpp \
|
||||||
src/providers/twitch/PubsubHelpers.cpp \
|
src/providers/twitch/PartialTwitchUser.cpp \
|
||||||
src/providers/twitch/TwitchAccount.cpp \
|
src/providers/twitch/PubsubActions.cpp \
|
||||||
src/providers/twitch/TwitchAccountManager.cpp \
|
src/providers/twitch/PubsubClient.cpp \
|
||||||
src/providers/twitch/TwitchApi.cpp \
|
src/providers/twitch/PubsubHelpers.cpp \
|
||||||
src/providers/twitch/TwitchBadges.cpp \
|
src/providers/twitch/TwitchAccount.cpp \
|
||||||
src/providers/twitch/TwitchChannel.cpp \
|
src/providers/twitch/TwitchAccountManager.cpp \
|
||||||
src/providers/twitch/TwitchEmotes.cpp \
|
src/providers/twitch/TwitchApi.cpp \
|
||||||
src/providers/twitch/TwitchHelpers.cpp \
|
src/providers/twitch/TwitchBadges.cpp \
|
||||||
src/providers/twitch/TwitchIrcServer.cpp \
|
src/providers/twitch/TwitchChannel.cpp \
|
||||||
src/providers/twitch/TwitchMessageBuilder.cpp \
|
src/providers/twitch/TwitchEmotes.cpp \
|
||||||
src/providers/twitch/TwitchParseCheerEmotes.cpp \
|
src/providers/twitch/TwitchHelpers.cpp \
|
||||||
src/providers/twitch/TwitchUser.cpp \
|
src/providers/twitch/TwitchIrcServer.cpp \
|
||||||
src/RunGui.cpp \
|
src/providers/twitch/TwitchMessageBuilder.cpp \
|
||||||
src/singletons/Badges.cpp \
|
src/providers/twitch/TwitchParseCheerEmotes.cpp \
|
||||||
src/singletons/Emotes.cpp \
|
src/providers/twitch/TwitchUser.cpp \
|
||||||
src/singletons/helper/GifTimer.cpp \
|
src/RunGui.cpp \
|
||||||
src/singletons/helper/LoggingChannel.cpp \
|
src/singletons/Badges.cpp \
|
||||||
src/singletons/Logging.cpp \
|
src/singletons/Emotes.cpp \
|
||||||
src/singletons/NativeMessaging.cpp \
|
src/singletons/helper/GifTimer.cpp \
|
||||||
src/singletons/Paths.cpp \
|
src/singletons/helper/LoggingChannel.cpp \
|
||||||
src/singletons/Resources.cpp \
|
src/singletons/Logging.cpp \
|
||||||
src/singletons/Settings.cpp \
|
src/singletons/NativeMessaging.cpp \
|
||||||
src/singletons/Theme.cpp \
|
src/singletons/Paths.cpp \
|
||||||
src/singletons/Toasts.cpp \
|
src/singletons/Resources.cpp \
|
||||||
src/singletons/TooltipPreviewImage.cpp \
|
src/singletons/Settings.cpp \
|
||||||
src/singletons/Updates.cpp \
|
src/singletons/Theme.cpp \
|
||||||
src/singletons/WindowManager.cpp \
|
src/singletons/Toasts.cpp \
|
||||||
src/util/DebugCount.cpp \
|
src/singletons/TooltipPreviewImage.cpp \
|
||||||
src/util/FormatTime.cpp \
|
src/singletons/Updates.cpp \
|
||||||
src/util/IncognitoBrowser.cpp \
|
src/singletons/WindowManager.cpp \
|
||||||
src/util/InitUpdateButton.cpp \
|
src/util/DebugCount.cpp \
|
||||||
src/util/JsonQuery.cpp \
|
src/util/FormatTime.cpp \
|
||||||
src/util/RapidjsonHelpers.cpp \
|
src/util/IncognitoBrowser.cpp \
|
||||||
src/util/StreamLink.cpp \
|
src/util/InitUpdateButton.cpp \
|
||||||
src/widgets/AccountSwitchPopup.cpp \
|
src/util/JsonQuery.cpp \
|
||||||
src/widgets/AccountSwitchWidget.cpp \
|
src/util/RapidjsonHelpers.cpp \
|
||||||
src/widgets/AttachedWindow.cpp \
|
src/util/StreamLink.cpp \
|
||||||
src/widgets/dialogs/EmotePopup.cpp \
|
src/widgets/AccountSwitchPopup.cpp \
|
||||||
src/widgets/dialogs/IrcConnectionEditor.cpp \
|
src/widgets/AccountSwitchWidget.cpp \
|
||||||
src/widgets/dialogs/LastRunCrashDialog.cpp \
|
src/widgets/AttachedWindow.cpp \
|
||||||
src/widgets/dialogs/LoginDialog.cpp \
|
src/widgets/dialogs/EmotePopup.cpp \
|
||||||
src/widgets/dialogs/LogsPopup.cpp \
|
src/widgets/dialogs/IrcConnectionEditor.cpp \
|
||||||
src/widgets/dialogs/NotificationPopup.cpp \
|
src/widgets/dialogs/LastRunCrashDialog.cpp \
|
||||||
src/widgets/dialogs/QualityPopup.cpp \
|
src/widgets/dialogs/LoginDialog.cpp \
|
||||||
src/widgets/dialogs/SelectChannelDialog.cpp \
|
src/widgets/dialogs/LogsPopup.cpp \
|
||||||
src/widgets/dialogs/SettingsDialog.cpp \
|
src/widgets/dialogs/NotificationPopup.cpp \
|
||||||
src/widgets/dialogs/TextInputDialog.cpp \
|
src/widgets/dialogs/QualityPopup.cpp \
|
||||||
src/widgets/dialogs/UpdateDialog.cpp \
|
src/widgets/dialogs/SelectChannelDialog.cpp \
|
||||||
src/widgets/dialogs/UserInfoPopup.cpp \
|
src/widgets/dialogs/SettingsDialog.cpp \
|
||||||
src/widgets/dialogs/WelcomeDialog.cpp \
|
src/widgets/dialogs/TextInputDialog.cpp \
|
||||||
src/widgets/helper/ChannelView.cpp \
|
src/widgets/dialogs/UpdateDialog.cpp \
|
||||||
src/widgets/helper/ComboBoxItemDelegate.cpp \
|
src/widgets/dialogs/UserInfoPopup.cpp \
|
||||||
src/widgets/helper/DebugPopup.cpp \
|
src/widgets/dialogs/WelcomeDialog.cpp \
|
||||||
src/widgets/helper/EditableModelView.cpp \
|
src/widgets/helper/ChannelView.cpp \
|
||||||
src/widgets/helper/NotebookButton.cpp \
|
src/widgets/helper/ComboBoxItemDelegate.cpp \
|
||||||
src/widgets/helper/NotebookTab.cpp \
|
src/widgets/helper/DebugPopup.cpp \
|
||||||
src/widgets/helper/ResizingTextEdit.cpp \
|
src/widgets/helper/EditableModelView.cpp \
|
||||||
src/widgets/helper/ScrollbarHighlight.cpp \
|
src/widgets/helper/NotebookButton.cpp \
|
||||||
src/widgets/helper/SearchPopup.cpp \
|
src/widgets/helper/NotebookTab.cpp \
|
||||||
src/widgets/helper/SettingsDialogTab.cpp \
|
src/widgets/helper/ResizingTextEdit.cpp \
|
||||||
src/widgets/Notebook.cpp \
|
src/widgets/helper/ScrollbarHighlight.cpp \
|
||||||
src/widgets/Scrollbar.cpp \
|
src/widgets/helper/SearchPopup.cpp \
|
||||||
src/widgets/settingspages/AboutPage.cpp \
|
src/widgets/helper/SettingsDialogTab.cpp \
|
||||||
src/widgets/settingspages/AccountsPage.cpp \
|
src/widgets/Notebook.cpp \
|
||||||
src/widgets/settingspages/CommandPage.cpp \
|
src/widgets/Scrollbar.cpp \
|
||||||
src/widgets/settingspages/ExternalToolsPage.cpp \
|
src/widgets/settingspages/AboutPage.cpp \
|
||||||
src/widgets/settingspages/GeneralPage.cpp \
|
src/widgets/settingspages/AccountsPage.cpp \
|
||||||
src/widgets/settingspages/HighlightingPage.cpp \
|
src/widgets/settingspages/CommandPage.cpp \
|
||||||
src/widgets/settingspages/IgnoresPage.cpp \
|
src/widgets/settingspages/ExternalToolsPage.cpp \
|
||||||
src/widgets/settingspages/KeyboardSettingsPage.cpp \
|
src/widgets/settingspages/GeneralPage.cpp \
|
||||||
src/widgets/settingspages/ModerationPage.cpp \
|
src/widgets/settingspages/HighlightingPage.cpp \
|
||||||
src/widgets/settingspages/NotificationPage.cpp \
|
src/widgets/settingspages/IgnoresPage.cpp \
|
||||||
src/widgets/settingspages/SettingsPage.cpp \
|
src/widgets/settingspages/KeyboardSettingsPage.cpp \
|
||||||
src/widgets/splits/ClosedSplits.cpp \
|
src/widgets/settingspages/ModerationPage.cpp \
|
||||||
src/widgets/splits/Split.cpp \
|
src/widgets/settingspages/NotificationPage.cpp \
|
||||||
src/widgets/splits/SplitContainer.cpp \
|
src/widgets/settingspages/SettingsPage.cpp \
|
||||||
src/widgets/splits/SplitHeader.cpp \
|
src/widgets/splits/ClosedSplits.cpp \
|
||||||
src/widgets/splits/SplitInput.cpp \
|
src/widgets/splits/Split.cpp \
|
||||||
src/widgets/splits/SplitOverlay.cpp \
|
src/widgets/splits/SplitContainer.cpp \
|
||||||
src/widgets/StreamView.cpp \
|
src/widgets/splits/SplitHeader.cpp \
|
||||||
src/widgets/Window.cpp \
|
src/widgets/splits/SplitInput.cpp \
|
||||||
|
src/widgets/splits/SplitOverlay.cpp \
|
||||||
HEADERS += \
|
src/widgets/StreamView.cpp \
|
||||||
src/Application.hpp \
|
src/widgets/Window.cpp \
|
||||||
src/autogenerated/ResourcesAutogen.hpp \
|
|
||||||
src/BrowserExtension.hpp \
|
HEADERS += \
|
||||||
src/common/Aliases.hpp \
|
src/Application.hpp \
|
||||||
src/common/Atomic.hpp \
|
src/autogenerated/ResourcesAutogen.hpp \
|
||||||
src/common/Channel.hpp \
|
src/BrowserExtension.hpp \
|
||||||
src/common/ChannelChatters.hpp \
|
src/common/Aliases.hpp \
|
||||||
src/common/Common.hpp \
|
src/common/Atomic.hpp \
|
||||||
src/common/CompletionModel.hpp \
|
src/common/Channel.hpp \
|
||||||
src/common/ConcurrentMap.hpp \
|
src/common/ChannelChatters.hpp \
|
||||||
src/common/Credentials.hpp \
|
src/common/Common.hpp \
|
||||||
src/common/DownloadManager.hpp \
|
src/common/CompletionModel.hpp \
|
||||||
src/common/Env.hpp \
|
src/common/ConcurrentMap.hpp \
|
||||||
src/common/LinkParser.hpp \
|
src/common/Credentials.hpp \
|
||||||
src/common/NetworkCommon.hpp \
|
src/common/DownloadManager.hpp \
|
||||||
src/common/NetworkManager.hpp \
|
src/common/Env.hpp \
|
||||||
src/common/NetworkPrivate.hpp \
|
src/common/LinkParser.hpp \
|
||||||
src/common/NetworkRequest.hpp \
|
src/common/Modes.hpp \
|
||||||
src/common/NetworkResult.hpp \
|
src/common/NetworkCommon.hpp \
|
||||||
src/common/NullablePtr.hpp \
|
src/common/NetworkManager.hpp \
|
||||||
src/common/ProviderId.hpp \
|
src/common/NetworkPrivate.hpp \
|
||||||
src/common/SignalVector.hpp \
|
src/common/NetworkRequest.hpp \
|
||||||
src/common/SignalVectorModel.hpp \
|
src/common/NetworkResult.hpp \
|
||||||
src/common/UniqueAccess.hpp \
|
src/common/NullablePtr.hpp \
|
||||||
src/common/UsernameSet.hpp \
|
src/common/ProviderId.hpp \
|
||||||
src/common/Version.hpp \
|
src/common/SignalVector.hpp \
|
||||||
src/controllers/accounts/Account.hpp \
|
src/common/SignalVectorModel.hpp \
|
||||||
src/controllers/accounts/AccountController.hpp \
|
src/common/UniqueAccess.hpp \
|
||||||
src/controllers/accounts/AccountModel.hpp \
|
src/common/UsernameSet.hpp \
|
||||||
src/controllers/commands/Command.hpp \
|
src/common/Version.hpp \
|
||||||
src/controllers/commands/CommandController.hpp \
|
src/controllers/accounts/Account.hpp \
|
||||||
src/controllers/commands/CommandModel.hpp \
|
src/controllers/accounts/AccountController.hpp \
|
||||||
src/controllers/highlights/HighlightBlacklistModel.hpp \
|
src/controllers/accounts/AccountModel.hpp \
|
||||||
src/controllers/highlights/HighlightBlacklistUser.hpp \
|
src/controllers/commands/Command.hpp \
|
||||||
src/controllers/highlights/HighlightController.hpp \
|
src/controllers/commands/CommandController.hpp \
|
||||||
src/controllers/highlights/HighlightModel.hpp \
|
src/controllers/commands/CommandModel.hpp \
|
||||||
src/controllers/highlights/HighlightPhrase.hpp \
|
src/controllers/highlights/HighlightBlacklistModel.hpp \
|
||||||
src/controllers/highlights/UserHighlightModel.hpp \
|
src/controllers/highlights/HighlightBlacklistUser.hpp \
|
||||||
src/controllers/ignores/IgnoreController.hpp \
|
src/controllers/highlights/HighlightController.hpp \
|
||||||
src/controllers/ignores/IgnoreModel.hpp \
|
src/controllers/highlights/HighlightModel.hpp \
|
||||||
src/controllers/ignores/IgnorePhrase.hpp \
|
src/controllers/highlights/HighlightPhrase.hpp \
|
||||||
src/controllers/moderationactions/ModerationAction.hpp \
|
src/controllers/highlights/UserHighlightModel.hpp \
|
||||||
src/controllers/moderationactions/ModerationActionModel.hpp \
|
src/controllers/ignores/IgnoreController.hpp \
|
||||||
src/controllers/moderationactions/ModerationActions.hpp \
|
src/controllers/ignores/IgnoreModel.hpp \
|
||||||
src/controllers/notifications/NotificationController.hpp \
|
src/controllers/ignores/IgnorePhrase.hpp \
|
||||||
src/controllers/notifications/NotificationModel.hpp \
|
src/controllers/moderationactions/ModerationAction.hpp \
|
||||||
src/controllers/pings/PingController.hpp \
|
src/controllers/moderationactions/ModerationActionModel.hpp \
|
||||||
src/controllers/pings/PingModel.hpp \
|
src/controllers/moderationactions/ModerationActions.hpp \
|
||||||
src/controllers/taggedusers/TaggedUser.hpp \
|
src/controllers/notifications/NotificationController.hpp \
|
||||||
src/controllers/taggedusers/TaggedUsersController.hpp \
|
src/controllers/notifications/NotificationModel.hpp \
|
||||||
src/controllers/taggedusers/TaggedUsersModel.hpp \
|
src/controllers/pings/PingController.hpp \
|
||||||
src/messages/Emote.hpp \
|
src/controllers/pings/PingModel.hpp \
|
||||||
src/messages/Image.hpp \
|
src/controllers/taggedusers/TaggedUser.hpp \
|
||||||
src/messages/ImageSet.hpp \
|
src/controllers/taggedusers/TaggedUsersController.hpp \
|
||||||
src/messages/layouts/MessageLayout.hpp \
|
src/controllers/taggedusers/TaggedUsersModel.hpp \
|
||||||
src/messages/layouts/MessageLayoutContainer.hpp \
|
src/ForwardDecl.hpp \
|
||||||
src/messages/layouts/MessageLayoutElement.hpp \
|
src/messages/Emote.hpp \
|
||||||
src/messages/LimitedQueue.hpp \
|
src/messages/Image.hpp \
|
||||||
src/messages/LimitedQueueSnapshot.hpp \
|
src/messages/ImageSet.hpp \
|
||||||
src/messages/Link.hpp \
|
src/messages/layouts/MessageLayout.hpp \
|
||||||
src/messages/Message.hpp \
|
src/messages/layouts/MessageLayoutContainer.hpp \
|
||||||
src/messages/MessageBuilder.hpp \
|
src/messages/layouts/MessageLayoutElement.hpp \
|
||||||
src/messages/MessageColor.hpp \
|
src/messages/LimitedQueue.hpp \
|
||||||
src/messages/MessageContainer.hpp \
|
src/messages/LimitedQueueSnapshot.hpp \
|
||||||
src/messages/MessageElement.hpp \
|
src/messages/Link.hpp \
|
||||||
src/messages/MessageParseArgs.hpp \
|
src/messages/Message.hpp \
|
||||||
src/messages/Selection.hpp \
|
src/messages/MessageBuilder.hpp \
|
||||||
src/PrecompiledHeader.hpp \
|
src/messages/MessageColor.hpp \
|
||||||
src/providers/bttv/BttvEmotes.hpp \
|
src/messages/MessageContainer.hpp \
|
||||||
src/providers/bttv/LoadBttvChannelEmote.hpp \
|
src/messages/MessageElement.hpp \
|
||||||
src/providers/chatterino/ChatterinoBadges.hpp \
|
src/messages/MessageParseArgs.hpp \
|
||||||
src/providers/emoji/Emojis.hpp \
|
src/messages/search/AuthorPredicate.hpp \
|
||||||
src/providers/ffz/FfzEmotes.hpp \
|
src/messages/search/LinkPredicate.hpp \
|
||||||
src/providers/ffz/FfzModBadge.hpp \
|
src/messages/search/MessagePredicate.hpp \
|
||||||
src/providers/irc/AbstractIrcServer.hpp \
|
src/messages/search/SubstringPredicate.hpp \
|
||||||
src/providers/irc/Irc2.hpp \
|
src/messages/Selection.hpp \
|
||||||
src/providers/irc/IrcAccount.hpp \
|
src/PrecompiledHeader.hpp \
|
||||||
src/providers/irc/IrcChannel2.hpp \
|
src/providers/bttv/BttvEmotes.hpp \
|
||||||
src/providers/irc/IrcCommands.hpp \
|
src/providers/bttv/LoadBttvChannelEmote.hpp \
|
||||||
src/providers/irc/IrcConnection2.hpp \
|
src/providers/chatterino/ChatterinoBadges.hpp \
|
||||||
src/providers/irc/IrcServer.hpp \
|
src/providers/emoji/Emojis.hpp \
|
||||||
src/providers/LinkResolver.hpp \
|
src/providers/ffz/FfzEmotes.hpp \
|
||||||
src/providers/twitch/ChatroomChannel.hpp \
|
src/providers/irc/AbstractIrcServer.hpp \
|
||||||
src/providers/twitch/EmoteValue.hpp \
|
src/providers/irc/Irc2.hpp \
|
||||||
src/providers/twitch/IrcMessageHandler.hpp \
|
src/providers/irc/IrcAccount.hpp \
|
||||||
src/providers/twitch/PartialTwitchUser.hpp \
|
src/providers/irc/IrcChannel2.hpp \
|
||||||
src/providers/twitch/PubsubActions.hpp \
|
src/providers/irc/IrcCommands.hpp \
|
||||||
src/providers/twitch/PubsubClient.hpp \
|
src/providers/irc/IrcConnection2.hpp \
|
||||||
src/providers/twitch/PubsubHelpers.hpp \
|
src/providers/irc/IrcServer.hpp \
|
||||||
src/providers/twitch/TwitchAccount.hpp \
|
src/providers/LinkResolver.hpp \
|
||||||
src/providers/twitch/TwitchAccountManager.hpp \
|
src/providers/twitch/ChatroomChannel.hpp \
|
||||||
src/providers/twitch/TwitchApi.hpp \
|
src/providers/twitch/EmoteValue.hpp \
|
||||||
src/providers/twitch/TwitchBadges.hpp \
|
src/providers/twitch/IrcMessageHandler.hpp \
|
||||||
src/providers/twitch/TwitchChannel.hpp \
|
src/providers/twitch/PartialTwitchUser.hpp \
|
||||||
src/providers/twitch/TwitchCommon.hpp \
|
src/providers/twitch/PubsubActions.hpp \
|
||||||
src/providers/twitch/TwitchEmotes.hpp \
|
src/providers/twitch/PubsubClient.hpp \
|
||||||
src/providers/twitch/TwitchHelpers.hpp \
|
src/providers/twitch/PubsubHelpers.hpp \
|
||||||
src/providers/twitch/TwitchIrcServer.hpp \
|
src/providers/twitch/TwitchAccount.hpp \
|
||||||
src/providers/twitch/TwitchMessageBuilder.hpp \
|
src/providers/twitch/TwitchAccountManager.hpp \
|
||||||
src/providers/twitch/TwitchParseCheerEmotes.hpp \
|
src/providers/twitch/TwitchApi.hpp \
|
||||||
src/providers/twitch/TwitchUser.hpp \
|
src/providers/twitch/TwitchBadges.hpp \
|
||||||
src/RunGui.hpp \
|
src/providers/twitch/TwitchChannel.hpp \
|
||||||
src/singletons/Badges.hpp \
|
src/providers/twitch/TwitchCommon.hpp \
|
||||||
src/singletons/Emotes.hpp \
|
src/providers/twitch/TwitchEmotes.hpp \
|
||||||
src/singletons/helper/GifTimer.hpp \
|
src/providers/twitch/TwitchHelpers.hpp \
|
||||||
src/singletons/helper/LoggingChannel.hpp \
|
src/providers/twitch/TwitchIrcServer.hpp \
|
||||||
src/singletons/Logging.hpp \
|
src/providers/twitch/TwitchMessageBuilder.hpp \
|
||||||
src/singletons/NativeMessaging.hpp \
|
src/providers/twitch/TwitchParseCheerEmotes.hpp \
|
||||||
src/singletons/Paths.hpp \
|
src/providers/twitch/TwitchUser.hpp \
|
||||||
src/singletons/Resources.hpp \
|
src/RunGui.hpp \
|
||||||
src/singletons/Settings.hpp \
|
src/singletons/Badges.hpp \
|
||||||
src/singletons/Theme.hpp \
|
src/singletons/Emotes.hpp \
|
||||||
src/singletons/Toasts.hpp \
|
src/singletons/helper/GifTimer.hpp \
|
||||||
src/singletons/TooltipPreviewImage.hpp \
|
src/singletons/helper/LoggingChannel.hpp \
|
||||||
src/singletons/Updates.hpp \
|
src/singletons/Logging.hpp \
|
||||||
src/singletons/WindowManager.hpp \
|
src/singletons/NativeMessaging.hpp \
|
||||||
src/util/ConcurrentMap.hpp \
|
src/singletons/Paths.hpp \
|
||||||
src/util/DebugCount.hpp \
|
src/singletons/Resources.hpp \
|
||||||
src/util/FormatTime.hpp \
|
src/singletons/Settings.hpp \
|
||||||
src/util/IncognitoBrowser.hpp \
|
src/singletons/Theme.hpp \
|
||||||
src/util/InitUpdateButton.hpp \
|
src/singletons/Toasts.hpp \
|
||||||
src/util/IrcHelpers.hpp \
|
src/singletons/TooltipPreviewImage.hpp \
|
||||||
src/util/IsBigEndian.hpp \
|
src/singletons/Updates.hpp \
|
||||||
src/util/JsonQuery.hpp \
|
src/singletons/WindowManager.hpp \
|
||||||
src/util/LayoutCreator.hpp \
|
src/util/ConcurrentMap.hpp \
|
||||||
src/util/Overloaded.hpp \
|
src/util/DebugCount.hpp \
|
||||||
src/util/QObjectRef.hpp \
|
src/util/FormatTime.hpp \
|
||||||
src/util/QStringHash.hpp \
|
src/util/IncognitoBrowser.hpp \
|
||||||
src/util/rangealgorithm.hpp \
|
src/util/InitUpdateButton.hpp \
|
||||||
src/util/RapidjsonHelpers.hpp \
|
src/util/IrcHelpers.hpp \
|
||||||
src/util/RemoveScrollAreaBackground.hpp \
|
src/util/IsBigEndian.hpp \
|
||||||
src/util/SharedPtrElementLess.hpp \
|
src/util/JsonQuery.hpp \
|
||||||
src/util/StandardItemHelper.hpp \
|
src/util/LayoutCreator.hpp \
|
||||||
src/util/StreamLink.hpp \
|
src/util/Overloaded.hpp \
|
||||||
src/widgets/AccountSwitchPopup.hpp \
|
src/util/QObjectRef.hpp \
|
||||||
src/widgets/AccountSwitchWidget.hpp \
|
src/util/QStringHash.hpp \
|
||||||
src/widgets/AttachedWindow.hpp \
|
src/util/rangealgorithm.hpp \
|
||||||
src/widgets/dialogs/EmotePopup.hpp \
|
src/util/RapidjsonHelpers.hpp \
|
||||||
src/widgets/dialogs/IrcConnectionEditor.hpp \
|
src/util/RemoveScrollAreaBackground.hpp \
|
||||||
src/widgets/dialogs/LastRunCrashDialog.hpp \
|
src/util/SampleCheerMessages.hpp \
|
||||||
src/widgets/dialogs/LoginDialog.hpp \
|
src/util/SharedPtrElementLess.hpp \
|
||||||
src/widgets/dialogs/LogsPopup.hpp \
|
src/util/StandardItemHelper.hpp \
|
||||||
src/widgets/dialogs/NotificationPopup.hpp \
|
src/util/StreamLink.hpp \
|
||||||
src/widgets/dialogs/QualityPopup.hpp \
|
src/widgets/AccountSwitchPopup.hpp \
|
||||||
src/widgets/dialogs/SelectChannelDialog.hpp \
|
src/widgets/AccountSwitchWidget.hpp \
|
||||||
src/widgets/dialogs/SettingsDialog.hpp \
|
src/widgets/AttachedWindow.hpp \
|
||||||
src/widgets/dialogs/TextInputDialog.hpp \
|
src/widgets/dialogs/EmotePopup.hpp \
|
||||||
src/widgets/dialogs/UpdateDialog.hpp \
|
src/widgets/dialogs/IrcConnectionEditor.hpp \
|
||||||
src/widgets/dialogs/UserInfoPopup.hpp \
|
src/widgets/dialogs/LastRunCrashDialog.hpp \
|
||||||
src/widgets/dialogs/WelcomeDialog.hpp \
|
src/widgets/dialogs/LoginDialog.hpp \
|
||||||
src/widgets/helper/ChannelView.hpp \
|
src/widgets/dialogs/LogsPopup.hpp \
|
||||||
src/widgets/helper/ComboBoxItemDelegate.hpp \
|
src/widgets/dialogs/NotificationPopup.hpp \
|
||||||
src/widgets/helper/CommonTexts.hpp \
|
src/widgets/dialogs/QualityPopup.hpp \
|
||||||
src/widgets/helper/DebugPopup.hpp \
|
src/widgets/dialogs/SelectChannelDialog.hpp \
|
||||||
src/widgets/helper/EditableModelView.hpp \
|
src/widgets/dialogs/SettingsDialog.hpp \
|
||||||
src/widgets/helper/Line.hpp \
|
src/widgets/dialogs/TextInputDialog.hpp \
|
||||||
src/widgets/helper/NotebookButton.hpp \
|
src/widgets/dialogs/UpdateDialog.hpp \
|
||||||
src/widgets/helper/NotebookTab.hpp \
|
src/widgets/dialogs/UserInfoPopup.hpp \
|
||||||
src/widgets/helper/ResizingTextEdit.hpp \
|
src/widgets/dialogs/WelcomeDialog.hpp \
|
||||||
src/widgets/helper/ScrollbarHighlight.hpp \
|
src/widgets/helper/ChannelView.hpp \
|
||||||
src/widgets/helper/SearchPopup.hpp \
|
src/widgets/helper/ComboBoxItemDelegate.hpp \
|
||||||
src/widgets/helper/SettingsDialogTab.hpp \
|
src/widgets/helper/CommonTexts.hpp \
|
||||||
src/widgets/Notebook.hpp \
|
src/widgets/helper/DebugPopup.hpp \
|
||||||
src/widgets/Scrollbar.hpp \
|
src/widgets/helper/EditableModelView.hpp \
|
||||||
src/widgets/settingspages/AboutPage.hpp \
|
src/widgets/helper/Line.hpp \
|
||||||
src/widgets/settingspages/AccountsPage.hpp \
|
src/widgets/helper/NotebookButton.hpp \
|
||||||
src/widgets/settingspages/CommandPage.hpp \
|
src/widgets/helper/NotebookTab.hpp \
|
||||||
src/widgets/settingspages/ExternalToolsPage.hpp \
|
src/widgets/helper/ResizingTextEdit.hpp \
|
||||||
src/widgets/settingspages/GeneralPage.hpp \
|
src/widgets/helper/ScrollbarHighlight.hpp \
|
||||||
src/widgets/settingspages/HighlightingPage.hpp \
|
src/widgets/helper/SearchPopup.hpp \
|
||||||
src/widgets/settingspages/IgnoresPage.hpp \
|
src/widgets/helper/SettingsDialogTab.hpp \
|
||||||
src/widgets/settingspages/KeyboardSettingsPage.hpp \
|
src/widgets/Notebook.hpp \
|
||||||
src/widgets/settingspages/ModerationPage.hpp \
|
src/widgets/Scrollbar.hpp \
|
||||||
src/widgets/settingspages/NotificationPage.hpp \
|
src/widgets/settingspages/AboutPage.hpp \
|
||||||
src/widgets/settingspages/SettingsPage.hpp \
|
src/widgets/settingspages/AccountsPage.hpp \
|
||||||
src/widgets/splits/ClosedSplits.hpp \
|
src/widgets/settingspages/CommandPage.hpp \
|
||||||
src/widgets/splits/Split.hpp \
|
src/widgets/settingspages/ExternalToolsPage.hpp \
|
||||||
src/widgets/splits/SplitContainer.hpp \
|
src/widgets/settingspages/GeneralPage.hpp \
|
||||||
src/widgets/splits/SplitHeader.hpp \
|
src/widgets/settingspages/HighlightingPage.hpp \
|
||||||
src/widgets/splits/SplitInput.hpp \
|
src/widgets/settingspages/IgnoresPage.hpp \
|
||||||
src/widgets/splits/SplitOverlay.hpp \
|
src/widgets/settingspages/KeyboardSettingsPage.hpp \
|
||||||
src/widgets/StreamView.hpp \
|
src/widgets/settingspages/ModerationPage.hpp \
|
||||||
src/widgets/Window.hpp \
|
src/widgets/settingspages/NotificationPage.hpp \
|
||||||
|
src/widgets/settingspages/SettingsPage.hpp \
|
||||||
RESOURCES += \
|
src/widgets/splits/ClosedSplits.hpp \
|
||||||
resources/resources.qrc \
|
src/widgets/splits/Split.hpp \
|
||||||
resources/resources_autogenerated.qrc
|
src/widgets/splits/SplitContainer.hpp \
|
||||||
|
src/widgets/splits/SplitHeader.hpp \
|
||||||
DISTFILES +=
|
src/widgets/splits/SplitInput.hpp \
|
||||||
|
src/widgets/splits/SplitOverlay.hpp \
|
||||||
FORMS += \
|
src/widgets/StreamView.hpp \
|
||||||
src/widgets/dialogs/IrcConnectionEditor.ui
|
src/widgets/Window.hpp \
|
||||||
|
|
||||||
# do not use windows min/max macros
|
RESOURCES += \
|
||||||
#win32 {
|
resources/resources.qrc \
|
||||||
# DEFINES += NOMINMAX
|
resources/resources_autogenerated.qrc
|
||||||
#}
|
|
||||||
|
DISTFILES +=
|
||||||
linux:isEmpty(PREFIX) {
|
|
||||||
message("Using default installation prefix (/usr/local). Change PREFIX in qmake command")
|
FORMS += \
|
||||||
PREFIX = /usr/local
|
src/widgets/dialogs/IrcConnectionEditor.ui
|
||||||
}
|
|
||||||
|
# do not use windows min/max macros
|
||||||
linux {
|
#win32 {
|
||||||
desktop.files = resources/chatterino.desktop
|
# DEFINES += NOMINMAX
|
||||||
desktop.path = $$PREFIX/share/applications
|
#}
|
||||||
|
|
||||||
build_icons.path = .
|
linux:isEmpty(PREFIX) {
|
||||||
build_icons.commands = @echo $$PWD && mkdir -p $$PWD/resources/linuxinstall/icons/hicolor/256x256 && cp $$PWD/resources/icon.png $$PWD/resources/linuxinstall/icons/hicolor/256x256/chatterino.png
|
message("Using default installation prefix (/usr/local). Change PREFIX in qmake command")
|
||||||
|
PREFIX = /usr/local
|
||||||
icon.files = $$PWD/resources/linuxinstall/icons/hicolor/256x256/chatterino.png
|
}
|
||||||
icon.path = $$PREFIX/share/icons/hicolor/256x256/apps
|
|
||||||
|
linux {
|
||||||
target.path = $$PREFIX/bin
|
desktop.files = resources/chatterino.desktop
|
||||||
|
desktop.path = $$PREFIX/share/applications
|
||||||
INSTALLS += desktop build_icons icon target
|
|
||||||
}
|
build_icons.path = .
|
||||||
|
build_icons.commands = @echo $$PWD && mkdir -p $$PWD/resources/linuxinstall/icons/hicolor/256x256 && cp $$PWD/resources/icon.png $$PWD/resources/linuxinstall/icons/hicolor/256x256/chatterino.png
|
||||||
git_commit=$$(GIT_COMMIT)
|
|
||||||
git_release=$$(GIT_RELEASE)
|
icon.files = $$PWD/resources/linuxinstall/icons/hicolor/256x256/chatterino.png
|
||||||
# Git data
|
icon.path = $$PREFIX/share/icons/hicolor/256x256/apps
|
||||||
isEmpty(git_commit) {
|
|
||||||
git_commit=$$system(git rev-parse HEAD)
|
target.path = $$PREFIX/bin
|
||||||
}
|
|
||||||
isEmpty(git_release) {
|
INSTALLS += desktop build_icons icon target
|
||||||
git_release=$$system(git describe)
|
}
|
||||||
}
|
|
||||||
git_hash = $$str_member($$git_commit, 0, 8)
|
git_commit=$$(GIT_COMMIT)
|
||||||
|
git_release=$$(GIT_RELEASE)
|
||||||
# Passing strings as defines requires you to use this weird triple-escape then quotation mark syntax.
|
# Git data
|
||||||
# https://stackoverflow.com/questions/3348711/add-a-define-to-qmake-with-a-value/18343449#18343449
|
isEmpty(git_commit) {
|
||||||
DEFINES += CHATTERINO_GIT_COMMIT=\\\"$$git_commit\\\"
|
git_commit=$$system(git rev-parse HEAD)
|
||||||
DEFINES += CHATTERINO_GIT_RELEASE=\\\"$$git_release\\\"
|
}
|
||||||
DEFINES += CHATTERINO_GIT_HASH=\\\"$$git_hash\\\"
|
isEmpty(git_release) {
|
||||||
|
git_release=$$system(git describe)
|
||||||
|
}
|
||||||
|
git_hash = $$str_member($$git_commit, 0, 8)
|
||||||
|
|
||||||
|
# Passing strings as defines requires you to use this weird triple-escape then quotation mark syntax.
|
||||||
|
# https://stackoverflow.com/questions/3348711/add-a-define-to-qmake-with-a-value/18343449#18343449
|
||||||
|
DEFINES += CHATTERINO_GIT_COMMIT=\\\"$$git_commit\\\"
|
||||||
|
DEFINES += CHATTERINO_GIT_RELEASE=\\\"$$git_release\\\"
|
||||||
|
DEFINES += CHATTERINO_GIT_HASH=\\\"$$git_hash\\\"
|
||||||
|
|||||||
+12
-12
@@ -1,12 +1,12 @@
|
|||||||
[requires]
|
[requires]
|
||||||
OpenSSL/1.0.2o@conan/stable
|
OpenSSL/1.0.2o@conan/stable
|
||||||
boost/1.69.0@conan/stable
|
boost/1.69.0@conan/stable
|
||||||
|
|
||||||
[generators]
|
[generators]
|
||||||
qmake
|
qmake
|
||||||
|
|
||||||
[options]
|
[options]
|
||||||
OpenSSL:shared=True
|
OpenSSL:shared=True
|
||||||
|
|
||||||
[imports]
|
[imports]
|
||||||
bin, *.dll -> ./Chatterino2 @ keep_path=False
|
bin, *.dll -> ./Chatterino2 @ keep_path=False
|
||||||
|
|||||||
+128
-128
@@ -1,128 +1,128 @@
|
|||||||
#include "BaseSettings.hpp"
|
#include "BaseSettings.hpp"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "util/Clamp.hpp"
|
#include "util/Clamp.hpp"
|
||||||
|
|
||||||
namespace AB_NAMESPACE {
|
namespace AB_NAMESPACE {
|
||||||
|
|
||||||
std::vector<std::weak_ptr<pajlada::Settings::SettingData>> _settings;
|
std::vector<std::weak_ptr<pajlada::Settings::SettingData>> _settings;
|
||||||
|
|
||||||
AB_SETTINGS_CLASS *AB_SETTINGS_CLASS::instance = nullptr;
|
AB_SETTINGS_CLASS *AB_SETTINGS_CLASS::instance = nullptr;
|
||||||
|
|
||||||
void _actuallyRegisterSetting(
|
void _actuallyRegisterSetting(
|
||||||
std::weak_ptr<pajlada::Settings::SettingData> setting)
|
std::weak_ptr<pajlada::Settings::SettingData> setting)
|
||||||
{
|
{
|
||||||
_settings.push_back(setting);
|
_settings.push_back(setting);
|
||||||
}
|
}
|
||||||
|
|
||||||
AB_SETTINGS_CLASS::AB_SETTINGS_CLASS(const QString &settingsDirectory)
|
AB_SETTINGS_CLASS::AB_SETTINGS_CLASS(const QString &settingsDirectory)
|
||||||
{
|
{
|
||||||
AB_SETTINGS_CLASS::instance = this;
|
AB_SETTINGS_CLASS::instance = this;
|
||||||
|
|
||||||
QString settingsPath = settingsDirectory + "/settings.json";
|
QString settingsPath = settingsDirectory + "/settings.json";
|
||||||
|
|
||||||
// get global instance of the settings library
|
// get global instance of the settings library
|
||||||
auto settingsInstance = pajlada::Settings::SettingManager::getInstance();
|
auto settingsInstance = pajlada::Settings::SettingManager::getInstance();
|
||||||
|
|
||||||
settingsInstance->load(qPrintable(settingsPath));
|
settingsInstance->load(qPrintable(settingsPath));
|
||||||
|
|
||||||
settingsInstance->setBackupEnabled(true);
|
settingsInstance->setBackupEnabled(true);
|
||||||
settingsInstance->setBackupSlots(9);
|
settingsInstance->setBackupSlots(9);
|
||||||
settingsInstance->saveMethod =
|
settingsInstance->saveMethod =
|
||||||
pajlada::Settings::SettingManager::SaveMethod::SaveOnExit;
|
pajlada::Settings::SettingManager::SaveMethod::SaveOnExit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AB_SETTINGS_CLASS::saveSnapshot()
|
void AB_SETTINGS_CLASS::saveSnapshot()
|
||||||
{
|
{
|
||||||
rapidjson::Document *d = new rapidjson::Document(rapidjson::kObjectType);
|
rapidjson::Document *d = new rapidjson::Document(rapidjson::kObjectType);
|
||||||
rapidjson::Document::AllocatorType &a = d->GetAllocator();
|
rapidjson::Document::AllocatorType &a = d->GetAllocator();
|
||||||
|
|
||||||
for (const auto &weakSetting : _settings)
|
for (const auto &weakSetting : _settings)
|
||||||
{
|
{
|
||||||
auto setting = weakSetting.lock();
|
auto setting = weakSetting.lock();
|
||||||
if (!setting)
|
if (!setting)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
rapidjson::Value key(setting->getPath().c_str(), a);
|
rapidjson::Value key(setting->getPath().c_str(), a);
|
||||||
auto curVal = setting->unmarshalJSON();
|
auto curVal = setting->unmarshalJSON();
|
||||||
if (curVal == nullptr)
|
if (curVal == nullptr)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
rapidjson::Value val;
|
rapidjson::Value val;
|
||||||
val.CopyFrom(*curVal, a);
|
val.CopyFrom(*curVal, a);
|
||||||
d->AddMember(key.Move(), val.Move(), a);
|
d->AddMember(key.Move(), val.Move(), a);
|
||||||
}
|
}
|
||||||
|
|
||||||
// log("Snapshot state: {}", rj::stringify(*d));
|
// log("Snapshot state: {}", rj::stringify(*d));
|
||||||
|
|
||||||
this->snapshot_.reset(d);
|
this->snapshot_.reset(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AB_SETTINGS_CLASS::restoreSnapshot()
|
void AB_SETTINGS_CLASS::restoreSnapshot()
|
||||||
{
|
{
|
||||||
if (!this->snapshot_)
|
if (!this->snapshot_)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &snapshot = *(this->snapshot_.get());
|
const auto &snapshot = *(this->snapshot_.get());
|
||||||
|
|
||||||
if (!snapshot.IsObject())
|
if (!snapshot.IsObject())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &weakSetting : _settings)
|
for (const auto &weakSetting : _settings)
|
||||||
{
|
{
|
||||||
auto setting = weakSetting.lock();
|
auto setting = weakSetting.lock();
|
||||||
if (!setting)
|
if (!setting)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *path = setting->getPath().c_str();
|
const char *path = setting->getPath().c_str();
|
||||||
|
|
||||||
if (!snapshot.HasMember(path))
|
if (!snapshot.HasMember(path))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
setting->marshalJSON(snapshot[path]);
|
setting->marshalJSON(snapshot[path]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float AB_SETTINGS_CLASS::getClampedUiScale() const
|
float AB_SETTINGS_CLASS::getClampedUiScale() const
|
||||||
{
|
{
|
||||||
return clamp<float>(this->uiScale.getValue(), 0.2f, 10);
|
return clamp<float>(this->uiScale.getValue(), 0.2f, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AB_SETTINGS_CLASS::setClampedUiScale(float value)
|
void AB_SETTINGS_CLASS::setClampedUiScale(float value)
|
||||||
{
|
{
|
||||||
this->uiScale.setValue(clamp<float>(value, 0.2f, 10));
|
this->uiScale.setValue(clamp<float>(value, 0.2f, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef AB_CUSTOM_SETTINGS
|
#ifndef AB_CUSTOM_SETTINGS
|
||||||
Settings *getSettings()
|
Settings *getSettings()
|
||||||
{
|
{
|
||||||
static_assert(std::is_same_v<AB_SETTINGS_CLASS, Settings>,
|
static_assert(std::is_same_v<AB_SETTINGS_CLASS, Settings>,
|
||||||
"`AB_SETTINGS_CLASS` must be the same as `Settings`");
|
"`AB_SETTINGS_CLASS` must be the same as `Settings`");
|
||||||
|
|
||||||
assert(AB_SETTINGS_CLASS::instance);
|
assert(AB_SETTINGS_CLASS::instance);
|
||||||
|
|
||||||
return AB_SETTINGS_CLASS::instance;
|
return AB_SETTINGS_CLASS::instance;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
AB_SETTINGS_CLASS *getABSettings()
|
AB_SETTINGS_CLASS *getABSettings()
|
||||||
{
|
{
|
||||||
assert(AB_SETTINGS_CLASS::instance);
|
assert(AB_SETTINGS_CLASS::instance);
|
||||||
|
|
||||||
return AB_SETTINGS_CLASS::instance;
|
return AB_SETTINGS_CLASS::instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|||||||
@@ -1,52 +1,52 @@
|
|||||||
#ifndef AB_SETTINGS_H
|
#ifndef AB_SETTINGS_H
|
||||||
#define AB_SETTINGS_H
|
#define AB_SETTINGS_H
|
||||||
|
|
||||||
#include <rapidjson/document.h>
|
#include <rapidjson/document.h>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <pajlada/settings/settingdata.hpp>
|
#include <pajlada/settings/settingdata.hpp>
|
||||||
|
|
||||||
#include "common/ChatterinoSetting.hpp"
|
#include "common/ChatterinoSetting.hpp"
|
||||||
|
|
||||||
#ifdef AB_CUSTOM_SETTINGS
|
#ifdef AB_CUSTOM_SETTINGS
|
||||||
# define AB_SETTINGS_CLASS ABSettings
|
# define AB_SETTINGS_CLASS ABSettings
|
||||||
#else
|
#else
|
||||||
# define AB_SETTINGS_CLASS Settings
|
# define AB_SETTINGS_CLASS Settings
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace AB_NAMESPACE {
|
namespace AB_NAMESPACE {
|
||||||
|
|
||||||
class Settings;
|
class Settings;
|
||||||
|
|
||||||
void _actuallyRegisterSetting(
|
void _actuallyRegisterSetting(
|
||||||
std::weak_ptr<pajlada::Settings::SettingData> setting);
|
std::weak_ptr<pajlada::Settings::SettingData> setting);
|
||||||
|
|
||||||
class AB_SETTINGS_CLASS
|
class AB_SETTINGS_CLASS
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AB_SETTINGS_CLASS(const QString &settingsDirectory);
|
AB_SETTINGS_CLASS(const QString &settingsDirectory);
|
||||||
|
|
||||||
void saveSnapshot();
|
void saveSnapshot();
|
||||||
void restoreSnapshot();
|
void restoreSnapshot();
|
||||||
|
|
||||||
static AB_SETTINGS_CLASS *instance;
|
static AB_SETTINGS_CLASS *instance;
|
||||||
|
|
||||||
FloatSetting uiScale = {"/appearance/uiScale2", 1};
|
FloatSetting uiScale = {"/appearance/uiScale2", 1};
|
||||||
BoolSetting windowTopMost = {"/appearance/windowAlwaysOnTop", false};
|
BoolSetting windowTopMost = {"/appearance/windowAlwaysOnTop", false};
|
||||||
|
|
||||||
float getClampedUiScale() const;
|
float getClampedUiScale() const;
|
||||||
void setClampedUiScale(float value);
|
void setClampedUiScale(float value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<rapidjson::Document> snapshot_;
|
std::unique_ptr<rapidjson::Document> snapshot_;
|
||||||
};
|
};
|
||||||
|
|
||||||
Settings *getSettings();
|
Settings *getSettings();
|
||||||
AB_SETTINGS_CLASS *getABSettings();
|
AB_SETTINGS_CLASS *getABSettings();
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|
||||||
#ifdef CHATTERINO
|
#ifdef CHATTERINO
|
||||||
# include "singletons/Settings.hpp"
|
# include "singletons/Settings.hpp"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+225
-225
@@ -1,225 +1,225 @@
|
|||||||
#include "BaseTheme.hpp"
|
#include "BaseTheme.hpp"
|
||||||
|
|
||||||
namespace AB_NAMESPACE {
|
namespace AB_NAMESPACE {
|
||||||
namespace {
|
namespace {
|
||||||
double getMultiplierByTheme(const QString &themeName)
|
double getMultiplierByTheme(const QString &themeName)
|
||||||
{
|
{
|
||||||
if (themeName == "Light")
|
if (themeName == "Light")
|
||||||
{
|
{
|
||||||
return 0.8;
|
return 0.8;
|
||||||
}
|
}
|
||||||
else if (themeName == "White")
|
else if (themeName == "White")
|
||||||
{
|
{
|
||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
else if (themeName == "Black")
|
else if (themeName == "Black")
|
||||||
{
|
{
|
||||||
return -1.0;
|
return -1.0;
|
||||||
}
|
}
|
||||||
else if (themeName == "Dark")
|
else if (themeName == "Dark")
|
||||||
{
|
{
|
||||||
return -0.8;
|
return -0.8;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
else if (themeName == "Custom")
|
else if (themeName == "Custom")
|
||||||
{
|
{
|
||||||
return getSettings()->customThemeMultiplier.getValue();
|
return getSettings()->customThemeMultiplier.getValue();
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return -0.8;
|
return -0.8;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool AB_THEME_CLASS::isLightTheme() const
|
bool AB_THEME_CLASS::isLightTheme() const
|
||||||
{
|
{
|
||||||
return this->isLight_;
|
return this->isLight_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AB_THEME_CLASS::update()
|
void AB_THEME_CLASS::update()
|
||||||
{
|
{
|
||||||
this->actuallyUpdate(this->themeHue,
|
this->actuallyUpdate(this->themeHue,
|
||||||
getMultiplierByTheme(this->themeName.getValue()));
|
getMultiplierByTheme(this->themeName.getValue()));
|
||||||
|
|
||||||
this->updated.invoke();
|
this->updated.invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AB_THEME_CLASS::actuallyUpdate(double hue, double multiplier)
|
void AB_THEME_CLASS::actuallyUpdate(double hue, double multiplier)
|
||||||
{
|
{
|
||||||
this->isLight_ = multiplier > 0;
|
this->isLight_ = multiplier > 0;
|
||||||
bool lightWin = isLight_;
|
bool lightWin = isLight_;
|
||||||
|
|
||||||
// QColor themeColor = QColor::fromHslF(hue, 0.43, 0.5);
|
// QColor themeColor = QColor::fromHslF(hue, 0.43, 0.5);
|
||||||
QColor themeColor = QColor::fromHslF(hue, 0.8, 0.5);
|
QColor themeColor = QColor::fromHslF(hue, 0.8, 0.5);
|
||||||
QColor themeColorNoSat = QColor::fromHslF(hue, 0, 0.5);
|
QColor themeColorNoSat = QColor::fromHslF(hue, 0, 0.5);
|
||||||
|
|
||||||
qreal sat = 0;
|
qreal sat = 0;
|
||||||
// 0.05;
|
// 0.05;
|
||||||
|
|
||||||
auto getColor = [multiplier](double h, double s, double l, double a = 1.0) {
|
auto getColor = [multiplier](double h, double s, double l, double a = 1.0) {
|
||||||
return QColor::fromHslF(h, s, ((l - 0.5) * multiplier) + 0.5, a);
|
return QColor::fromHslF(h, s, ((l - 0.5) * multiplier) + 0.5, a);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// WINDOW
|
/// WINDOW
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
this->window.background = lightWin ? "#fff" : QColor(61, 60, 56);
|
this->window.background = lightWin ? "#fff" : QColor(61, 60, 56);
|
||||||
#else
|
#else
|
||||||
this->window.background = lightWin ? "#fff" : "#111";
|
this->window.background = lightWin ? "#fff" : "#111";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QColor fg = this->window.text = lightWin ? "#000" : "#eee";
|
QColor fg = this->window.text = lightWin ? "#000" : "#eee";
|
||||||
this->window.borderFocused = lightWin ? "#ccc" : themeColor;
|
this->window.borderFocused = lightWin ? "#ccc" : themeColor;
|
||||||
this->window.borderUnfocused = lightWin ? "#ccc" : themeColorNoSat;
|
this->window.borderUnfocused = lightWin ? "#ccc" : themeColorNoSat;
|
||||||
|
|
||||||
// Ubuntu style
|
// Ubuntu style
|
||||||
// TODO: add setting for this
|
// TODO: add setting for this
|
||||||
// TabText = QColor(210, 210, 210);
|
// TabText = QColor(210, 210, 210);
|
||||||
// TabBackground = QColor(61, 60, 56);
|
// TabBackground = QColor(61, 60, 56);
|
||||||
// TabHoverText = QColor(210, 210, 210);
|
// TabHoverText = QColor(210, 210, 210);
|
||||||
// TabHoverBackground = QColor(73, 72, 68);
|
// TabHoverBackground = QColor(73, 72, 68);
|
||||||
|
|
||||||
// message (referenced later)
|
// message (referenced later)
|
||||||
this->messages.textColors.caret = //
|
this->messages.textColors.caret = //
|
||||||
this->messages.textColors.regular = isLight_ ? "#000" : "#fff";
|
this->messages.textColors.regular = isLight_ ? "#000" : "#fff";
|
||||||
|
|
||||||
QColor highlighted = lightWin ? QColor("#ff0000") : QColor("#ee6166");
|
QColor highlighted = lightWin ? QColor("#ff0000") : QColor("#ee6166");
|
||||||
|
|
||||||
/// TABS
|
/// TABS
|
||||||
if (lightWin)
|
if (lightWin)
|
||||||
{
|
{
|
||||||
this->tabs.regular = {
|
this->tabs.regular = {
|
||||||
QColor("#444"),
|
QColor("#444"),
|
||||||
{QColor("#fff"), QColor("#eee"), QColor("#fff")},
|
{QColor("#fff"), QColor("#eee"), QColor("#fff")},
|
||||||
{QColor("#fff"), QColor("#fff"), QColor("#fff")}};
|
{QColor("#fff"), QColor("#fff"), QColor("#fff")}};
|
||||||
this->tabs.newMessage = {
|
this->tabs.newMessage = {
|
||||||
QColor("#222"),
|
QColor("#222"),
|
||||||
{QColor("#fff"), QColor("#eee"), QColor("#fff")},
|
{QColor("#fff"), QColor("#eee"), QColor("#fff")},
|
||||||
{QColor("#bbb"), QColor("#bbb"), QColor("#bbb")}};
|
{QColor("#bbb"), QColor("#bbb"), QColor("#bbb")}};
|
||||||
this->tabs.highlighted = {
|
this->tabs.highlighted = {
|
||||||
fg,
|
fg,
|
||||||
{QColor("#fff"), QColor("#eee"), QColor("#fff")},
|
{QColor("#fff"), QColor("#eee"), QColor("#fff")},
|
||||||
{highlighted, highlighted, highlighted}};
|
{highlighted, highlighted, highlighted}};
|
||||||
this->tabs.selected = {
|
this->tabs.selected = {
|
||||||
QColor("#000"),
|
QColor("#000"),
|
||||||
{QColor("#b4d7ff"), QColor("#b4d7ff"), QColor("#b4d7ff")},
|
{QColor("#b4d7ff"), QColor("#b4d7ff"), QColor("#b4d7ff")},
|
||||||
{QColor("#00aeef"), QColor("#00aeef"), QColor("#00aeef")}};
|
{QColor("#00aeef"), QColor("#00aeef"), QColor("#00aeef")}};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->tabs.regular = {
|
this->tabs.regular = {
|
||||||
QColor("#aaa"),
|
QColor("#aaa"),
|
||||||
{QColor("#252525"), QColor("#252525"), QColor("#252525")},
|
{QColor("#252525"), QColor("#252525"), QColor("#252525")},
|
||||||
{QColor("#444"), QColor("#444"), QColor("#444")}};
|
{QColor("#444"), QColor("#444"), QColor("#444")}};
|
||||||
this->tabs.newMessage = {
|
this->tabs.newMessage = {
|
||||||
fg,
|
fg,
|
||||||
{QColor("#252525"), QColor("#252525"), QColor("#252525")},
|
{QColor("#252525"), QColor("#252525"), QColor("#252525")},
|
||||||
{QColor("#888"), QColor("#888"), QColor("#888")}};
|
{QColor("#888"), QColor("#888"), QColor("#888")}};
|
||||||
this->tabs.highlighted = {
|
this->tabs.highlighted = {
|
||||||
fg,
|
fg,
|
||||||
{QColor("#252525"), QColor("#252525"), QColor("#252525")},
|
{QColor("#252525"), QColor("#252525"), QColor("#252525")},
|
||||||
{highlighted, highlighted, highlighted}};
|
{highlighted, highlighted, highlighted}};
|
||||||
|
|
||||||
this->tabs.selected = {
|
this->tabs.selected = {
|
||||||
QColor("#fff"),
|
QColor("#fff"),
|
||||||
{QColor("#555555"), QColor("#555555"), QColor("#555555")},
|
{QColor("#555555"), QColor("#555555"), QColor("#555555")},
|
||||||
{QColor("#00aeef"), QColor("#00aeef"), QColor("#00aeef")}};
|
{QColor("#00aeef"), QColor("#00aeef"), QColor("#00aeef")}};
|
||||||
}
|
}
|
||||||
|
|
||||||
// scrollbar
|
// scrollbar
|
||||||
this->scrollbars.highlights.highlight = QColor("#ee6166");
|
this->scrollbars.highlights.highlight = QColor("#ee6166");
|
||||||
this->scrollbars.highlights.subscription = QColor("#C466FF");
|
this->scrollbars.highlights.subscription = QColor("#C466FF");
|
||||||
|
|
||||||
// this->tabs.newMessage = {
|
// this->tabs.newMessage = {
|
||||||
// fg,
|
// fg,
|
||||||
// {QBrush(blendColors(themeColor, "#ccc", 0.9), Qt::FDiagPattern),
|
// {QBrush(blendColors(themeColor, "#ccc", 0.9), Qt::FDiagPattern),
|
||||||
// QBrush(blendColors(themeColor, "#ccc", 0.9), Qt::FDiagPattern),
|
// QBrush(blendColors(themeColor, "#ccc", 0.9), Qt::FDiagPattern),
|
||||||
// QBrush(blendColors(themeColorNoSat, "#ccc", 0.9),
|
// QBrush(blendColors(themeColorNoSat, "#ccc", 0.9),
|
||||||
// Qt::FDiagPattern)}};
|
// Qt::FDiagPattern)}};
|
||||||
|
|
||||||
// this->tabs.newMessage = {
|
// this->tabs.newMessage = {
|
||||||
// fg,
|
// fg,
|
||||||
// {QBrush(blendColors(themeColor, "#666", 0.7),
|
// {QBrush(blendColors(themeColor, "#666", 0.7),
|
||||||
// Qt::FDiagPattern),
|
// Qt::FDiagPattern),
|
||||||
// QBrush(blendColors(themeColor, "#666", 0.5),
|
// QBrush(blendColors(themeColor, "#666", 0.5),
|
||||||
// Qt::FDiagPattern),
|
// Qt::FDiagPattern),
|
||||||
// QBrush(blendColors(themeColorNoSat, "#666", 0.7),
|
// QBrush(blendColors(themeColorNoSat, "#666", 0.7),
|
||||||
// Qt::FDiagPattern)}};
|
// Qt::FDiagPattern)}};
|
||||||
// this->tabs.highlighted = {fg, {QColor("#777"),
|
// this->tabs.highlighted = {fg, {QColor("#777"),
|
||||||
// QColor("#777"), QColor("#666")}};
|
// QColor("#777"), QColor("#666")}};
|
||||||
|
|
||||||
this->tabs.bottomLine = this->tabs.selected.backgrounds.regular.color();
|
this->tabs.bottomLine = this->tabs.selected.backgrounds.regular.color();
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|
||||||
// Split
|
// Split
|
||||||
bool flat = isLight_;
|
bool flat = isLight_;
|
||||||
|
|
||||||
// Message
|
// Message
|
||||||
this->messages.textColors.link =
|
this->messages.textColors.link =
|
||||||
isLight_ ? QColor(66, 134, 244) : QColor(66, 134, 244);
|
isLight_ ? QColor(66, 134, 244) : QColor(66, 134, 244);
|
||||||
this->messages.textColors.system = QColor(140, 127, 127);
|
this->messages.textColors.system = QColor(140, 127, 127);
|
||||||
|
|
||||||
this->messages.backgrounds.regular = getColor(0, sat, 1);
|
this->messages.backgrounds.regular = getColor(0, sat, 1);
|
||||||
this->messages.backgrounds.alternate = getColor(0, sat, 0.96);
|
this->messages.backgrounds.alternate = getColor(0, sat, 0.96);
|
||||||
|
|
||||||
if (isLight_)
|
if (isLight_)
|
||||||
{
|
{
|
||||||
this->messages.backgrounds.highlighted =
|
this->messages.backgrounds.highlighted =
|
||||||
blendColors(themeColor, this->messages.backgrounds.regular, 0.8);
|
blendColors(themeColor, this->messages.backgrounds.regular, 0.8);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// REMOVED
|
// REMOVED
|
||||||
// this->messages.backgrounds.highlighted =
|
// this->messages.backgrounds.highlighted =
|
||||||
// QColor(getSettings()->highlightColor);
|
// QColor(getSettings()->highlightColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->messages.backgrounds.subscription =
|
this->messages.backgrounds.subscription =
|
||||||
blendColors(QColor("#C466FF"), this->messages.backgrounds.regular, 0.7);
|
blendColors(QColor("#C466FF"), this->messages.backgrounds.regular, 0.7);
|
||||||
|
|
||||||
// this->messages.backgrounds.resub
|
// this->messages.backgrounds.resub
|
||||||
// this->messages.backgrounds.whisper
|
// this->messages.backgrounds.whisper
|
||||||
this->messages.disabled = getColor(0, sat, 1, 0.6);
|
this->messages.disabled = getColor(0, sat, 1, 0.6);
|
||||||
// this->messages.seperator =
|
// this->messages.seperator =
|
||||||
// this->messages.seperatorInner =
|
// this->messages.seperatorInner =
|
||||||
|
|
||||||
// Scrollbar
|
// Scrollbar
|
||||||
this->scrollbars.background = QColor(0, 0, 0, 0);
|
this->scrollbars.background = QColor(0, 0, 0, 0);
|
||||||
// this->scrollbars.background = splits.background;
|
// this->scrollbars.background = splits.background;
|
||||||
// this->scrollbars.background.setAlphaF(qreal(0.2));
|
// this->scrollbars.background.setAlphaF(qreal(0.2));
|
||||||
this->scrollbars.thumb = getColor(0, sat, 0.70);
|
this->scrollbars.thumb = getColor(0, sat, 0.70);
|
||||||
this->scrollbars.thumbSelected = getColor(0, sat, 0.65);
|
this->scrollbars.thumbSelected = getColor(0, sat, 0.65);
|
||||||
|
|
||||||
// tooltip
|
// tooltip
|
||||||
this->tooltip.background = QColor(0, 0, 0);
|
this->tooltip.background = QColor(0, 0, 0);
|
||||||
this->tooltip.text = QColor(255, 255, 255);
|
this->tooltip.text = QColor(255, 255, 255);
|
||||||
|
|
||||||
// Selection
|
// Selection
|
||||||
this->messages.selection =
|
this->messages.selection =
|
||||||
isLightTheme() ? QColor(0, 0, 0, 64) : QColor(255, 255, 255, 64);
|
isLightTheme() ? QColor(0, 0, 0, 64) : QColor(255, 255, 255, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor AB_THEME_CLASS::blendColors(const QColor &color1, const QColor &color2,
|
QColor AB_THEME_CLASS::blendColors(const QColor &color1, const QColor &color2,
|
||||||
qreal ratio)
|
qreal ratio)
|
||||||
{
|
{
|
||||||
int r = int(color1.red() * (1 - ratio) + color2.red() * ratio);
|
int r = int(color1.red() * (1 - ratio) + color2.red() * ratio);
|
||||||
int g = int(color1.green() * (1 - ratio) + color2.green() * ratio);
|
int g = int(color1.green() * (1 - ratio) + color2.green() * ratio);
|
||||||
int b = int(color1.blue() * (1 - ratio) + color2.blue() * ratio);
|
int b = int(color1.blue() * (1 - ratio) + color2.blue() * ratio);
|
||||||
|
|
||||||
return QColor(r, g, b, 255);
|
return QColor(r, g, b, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef AB_CUSTOM_THEME
|
#ifndef AB_CUSTOM_THEME
|
||||||
Theme *getTheme()
|
Theme *getTheme()
|
||||||
{
|
{
|
||||||
static auto theme = [] {
|
static auto theme = [] {
|
||||||
auto theme = new Theme();
|
auto theme = new Theme();
|
||||||
theme->update();
|
theme->update();
|
||||||
return theme;
|
return theme;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
return theme;
|
return theme;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|||||||
+117
-117
@@ -1,117 +1,117 @@
|
|||||||
#ifndef AB_THEME_H
|
#ifndef AB_THEME_H
|
||||||
#define AB_THEME_H
|
#define AB_THEME_H
|
||||||
|
|
||||||
#include <QBrush>
|
#include <QBrush>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <common/ChatterinoSetting.hpp>
|
#include <common/ChatterinoSetting.hpp>
|
||||||
|
|
||||||
#ifdef AB_CUSTOM_THEME
|
#ifdef AB_CUSTOM_THEME
|
||||||
# define AB_THEME_CLASS BaseTheme
|
# define AB_THEME_CLASS BaseTheme
|
||||||
#else
|
#else
|
||||||
# define AB_THEME_CLASS Theme
|
# define AB_THEME_CLASS Theme
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace AB_NAMESPACE {
|
namespace AB_NAMESPACE {
|
||||||
|
|
||||||
class Theme;
|
class Theme;
|
||||||
|
|
||||||
class AB_THEME_CLASS
|
class AB_THEME_CLASS
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool isLightTheme() const;
|
bool isLightTheme() const;
|
||||||
|
|
||||||
struct TabColors {
|
struct TabColors {
|
||||||
QColor text;
|
QColor text;
|
||||||
struct {
|
struct {
|
||||||
QBrush regular;
|
QBrush regular;
|
||||||
QBrush hover;
|
QBrush hover;
|
||||||
QBrush unfocused;
|
QBrush unfocused;
|
||||||
} backgrounds;
|
} backgrounds;
|
||||||
struct {
|
struct {
|
||||||
QColor regular;
|
QColor regular;
|
||||||
QColor hover;
|
QColor hover;
|
||||||
QColor unfocused;
|
QColor unfocused;
|
||||||
} line;
|
} line;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// WINDOW
|
/// WINDOW
|
||||||
struct {
|
struct {
|
||||||
QColor background;
|
QColor background;
|
||||||
QColor text;
|
QColor text;
|
||||||
QColor borderUnfocused;
|
QColor borderUnfocused;
|
||||||
QColor borderFocused;
|
QColor borderFocused;
|
||||||
} window;
|
} window;
|
||||||
|
|
||||||
/// TABS
|
/// TABS
|
||||||
struct {
|
struct {
|
||||||
TabColors regular;
|
TabColors regular;
|
||||||
TabColors newMessage;
|
TabColors newMessage;
|
||||||
TabColors highlighted;
|
TabColors highlighted;
|
||||||
TabColors selected;
|
TabColors selected;
|
||||||
QColor border;
|
QColor border;
|
||||||
QColor bottomLine;
|
QColor bottomLine;
|
||||||
} tabs;
|
} tabs;
|
||||||
|
|
||||||
/// MESSAGES
|
/// MESSAGES
|
||||||
struct {
|
struct {
|
||||||
struct {
|
struct {
|
||||||
QColor regular;
|
QColor regular;
|
||||||
QColor caret;
|
QColor caret;
|
||||||
QColor link;
|
QColor link;
|
||||||
QColor system;
|
QColor system;
|
||||||
} textColors;
|
} textColors;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
QColor regular;
|
QColor regular;
|
||||||
QColor alternate;
|
QColor alternate;
|
||||||
QColor highlighted;
|
QColor highlighted;
|
||||||
QColor subscription;
|
QColor subscription;
|
||||||
// QColor whisper;
|
// QColor whisper;
|
||||||
} backgrounds;
|
} backgrounds;
|
||||||
|
|
||||||
QColor disabled;
|
QColor disabled;
|
||||||
// QColor seperator;
|
// QColor seperator;
|
||||||
// QColor seperatorInner;
|
// QColor seperatorInner;
|
||||||
QColor selection;
|
QColor selection;
|
||||||
} messages;
|
} messages;
|
||||||
|
|
||||||
/// SCROLLBAR
|
/// SCROLLBAR
|
||||||
struct {
|
struct {
|
||||||
QColor background;
|
QColor background;
|
||||||
QColor thumb;
|
QColor thumb;
|
||||||
QColor thumbSelected;
|
QColor thumbSelected;
|
||||||
struct {
|
struct {
|
||||||
QColor highlight;
|
QColor highlight;
|
||||||
QColor subscription;
|
QColor subscription;
|
||||||
} highlights;
|
} highlights;
|
||||||
} scrollbars;
|
} scrollbars;
|
||||||
|
|
||||||
/// TOOLTIP
|
/// TOOLTIP
|
||||||
struct {
|
struct {
|
||||||
QColor text;
|
QColor text;
|
||||||
QColor background;
|
QColor background;
|
||||||
} tooltip;
|
} tooltip;
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
virtual void actuallyUpdate(double hue, double multiplier);
|
virtual void actuallyUpdate(double hue, double multiplier);
|
||||||
QColor blendColors(const QColor &color1, const QColor &color2, qreal ratio);
|
QColor blendColors(const QColor &color1, const QColor &color2, qreal ratio);
|
||||||
|
|
||||||
pajlada::Signals::NoArgSignal updated;
|
pajlada::Signals::NoArgSignal updated;
|
||||||
|
|
||||||
QStringSetting themeName{"/appearance/theme/name", "Dark"};
|
QStringSetting themeName{"/appearance/theme/name", "Dark"};
|
||||||
DoubleSetting themeHue{"/appearance/theme/hue", 0.0};
|
DoubleSetting themeHue{"/appearance/theme/hue", 0.0};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isLight_ = false;
|
bool isLight_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implemented in parent project if AB_CUSTOM_THEME is set.
|
// Implemented in parent project if AB_CUSTOM_THEME is set.
|
||||||
// Otherwise implemented in BaseThemecpp
|
// Otherwise implemented in BaseThemecpp
|
||||||
Theme *getTheme();
|
Theme *getTheme();
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|
||||||
#ifdef CHATTERINO
|
#ifdef CHATTERINO
|
||||||
# include "singletons/Theme.hpp"
|
# include "singletons/Theme.hpp"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,54 +1,54 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <pajlada/settings.hpp>
|
#include <pajlada/settings.hpp>
|
||||||
|
|
||||||
namespace AB_NAMESPACE {
|
namespace AB_NAMESPACE {
|
||||||
|
|
||||||
void _registerSetting(std::weak_ptr<pajlada::Settings::SettingData> setting);
|
void _registerSetting(std::weak_ptr<pajlada::Settings::SettingData> setting);
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
class ChatterinoSetting : public pajlada::Settings::Setting<Type>
|
class ChatterinoSetting : public pajlada::Settings::Setting<Type>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ChatterinoSetting(const std::string &path)
|
ChatterinoSetting(const std::string &path)
|
||||||
: pajlada::Settings::Setting<Type>(path)
|
: pajlada::Settings::Setting<Type>(path)
|
||||||
{
|
{
|
||||||
_registerSetting(this->getData());
|
_registerSetting(this->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatterinoSetting(const std::string &path, const Type &defaultValue)
|
ChatterinoSetting(const std::string &path, const Type &defaultValue)
|
||||||
: pajlada::Settings::Setting<Type>(path, defaultValue)
|
: pajlada::Settings::Setting<Type>(path, defaultValue)
|
||||||
{
|
{
|
||||||
_registerSetting(this->getData());
|
_registerSetting(this->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T2>
|
template <typename T2>
|
||||||
ChatterinoSetting &operator=(const T2 &newValue)
|
ChatterinoSetting &operator=(const T2 &newValue)
|
||||||
{
|
{
|
||||||
this->setValue(newValue);
|
this->setValue(newValue);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatterinoSetting &operator=(Type &&newValue) noexcept
|
ChatterinoSetting &operator=(Type &&newValue) noexcept
|
||||||
{
|
{
|
||||||
pajlada::Settings::Setting<Type>::operator=(newValue);
|
pajlada::Settings::Setting<Type>::operator=(newValue);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
using pajlada::Settings::Setting<Type>::operator==;
|
using pajlada::Settings::Setting<Type>::operator==;
|
||||||
using pajlada::Settings::Setting<Type>::operator!=;
|
using pajlada::Settings::Setting<Type>::operator!=;
|
||||||
|
|
||||||
using pajlada::Settings::Setting<Type>::operator Type;
|
using pajlada::Settings::Setting<Type>::operator Type;
|
||||||
};
|
};
|
||||||
|
|
||||||
using BoolSetting = ChatterinoSetting<bool>;
|
using BoolSetting = ChatterinoSetting<bool>;
|
||||||
using FloatSetting = ChatterinoSetting<float>;
|
using FloatSetting = ChatterinoSetting<float>;
|
||||||
using DoubleSetting = ChatterinoSetting<double>;
|
using DoubleSetting = ChatterinoSetting<double>;
|
||||||
using IntSetting = ChatterinoSetting<int>;
|
using IntSetting = ChatterinoSetting<int>;
|
||||||
using StringSetting = ChatterinoSetting<std::string>;
|
using StringSetting = ChatterinoSetting<std::string>;
|
||||||
using QStringSetting = ChatterinoSetting<QString>;
|
using QStringSetting = ChatterinoSetting<QString>;
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|||||||
@@ -1,82 +1,82 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
template <typename T, typename Q = typename std::underlying_type<T>::type>
|
template <typename T, typename Q = typename std::underlying_type<T>::type>
|
||||||
class FlagsEnum
|
class FlagsEnum
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FlagsEnum()
|
FlagsEnum()
|
||||||
: value_(static_cast<T>(0))
|
: value_(static_cast<T>(0))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
FlagsEnum(T value)
|
FlagsEnum(T value)
|
||||||
: value_(value)
|
: value_(value)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
FlagsEnum(std::initializer_list<T> flags)
|
FlagsEnum(std::initializer_list<T> flags)
|
||||||
{
|
{
|
||||||
for (auto flag : flags)
|
for (auto flag : flags)
|
||||||
{
|
{
|
||||||
this->set(flag);
|
this->set(flag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const FlagsEnum<T> &other)
|
bool operator==(const FlagsEnum<T> &other)
|
||||||
{
|
{
|
||||||
return this->value_ == other.value_;
|
return this->value_ == other.value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const FlagsEnum &other)
|
bool operator!=(const FlagsEnum &other)
|
||||||
{
|
{
|
||||||
return this->value_ != other.value_;
|
return this->value_ != other.value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(T flag)
|
void set(T flag)
|
||||||
{
|
{
|
||||||
reinterpret_cast<Q &>(this->value_) |= static_cast<Q>(flag);
|
reinterpret_cast<Q &>(this->value_) |= static_cast<Q>(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unset(T flag)
|
void unset(T flag)
|
||||||
{
|
{
|
||||||
reinterpret_cast<Q &>(this->value_) &= ~static_cast<Q>(flag);
|
reinterpret_cast<Q &>(this->value_) &= ~static_cast<Q>(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(T flag, bool value)
|
void set(T flag, bool value)
|
||||||
{
|
{
|
||||||
if (value)
|
if (value)
|
||||||
this->set(flag);
|
this->set(flag);
|
||||||
else
|
else
|
||||||
this->unset(flag);
|
this->unset(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has(T flag) const
|
bool has(T flag) const
|
||||||
{
|
{
|
||||||
return static_cast<Q>(this->value_) & static_cast<Q>(flag);
|
return static_cast<Q>(this->value_) & static_cast<Q>(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasAny(FlagsEnum flags) const
|
bool hasAny(FlagsEnum flags) const
|
||||||
{
|
{
|
||||||
return static_cast<Q>(this->value_) & static_cast<Q>(flags.value_);
|
return static_cast<Q>(this->value_) & static_cast<Q>(flags.value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasAll(FlagsEnum<T> flags) const
|
bool hasAll(FlagsEnum<T> flags) const
|
||||||
{
|
{
|
||||||
return (static_cast<Q>(this->value_) & static_cast<Q>(flags.value_)) &&
|
return (static_cast<Q>(this->value_) & static_cast<Q>(flags.value_)) &&
|
||||||
static_cast<Q>(flags->value);
|
static_cast<Q>(flags->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasNone(std::initializer_list<T> flags) const
|
bool hasNone(std::initializer_list<T> flags) const
|
||||||
{
|
{
|
||||||
return !this->hasAny(flags);
|
return !this->hasAny(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T value_{};
|
T value_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
namespace AB_NAMESPACE {
|
namespace AB_NAMESPACE {
|
||||||
|
|
||||||
class Settings;
|
class Settings;
|
||||||
class Paths;
|
class Paths;
|
||||||
|
|
||||||
class Singleton : boost::noncopyable
|
class Singleton : boost::noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Singleton() = default;
|
virtual ~Singleton() = default;
|
||||||
|
|
||||||
virtual void initialize(Settings &settings, Paths &paths)
|
virtual void initialize(Settings &settings, Paths &paths)
|
||||||
{
|
{
|
||||||
(void)(settings);
|
(void)(settings);
|
||||||
(void)(paths);
|
(void)(paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void save()
|
virtual void save()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
namespace AB_NAMESPACE {
|
namespace AB_NAMESPACE {
|
||||||
|
|
||||||
static bool isGuiThread()
|
static bool isGuiThread()
|
||||||
{
|
{
|
||||||
return QCoreApplication::instance()->thread() == QThread::currentThread();
|
return QCoreApplication::instance()->thread() == QThread::currentThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void assertInGuiThread()
|
static void assertInGuiThread()
|
||||||
{
|
{
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
assert(isGuiThread());
|
assert(isGuiThread());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
#include "Benchmark.hpp"
|
#include "Benchmark.hpp"
|
||||||
|
|
||||||
namespace AB_NAMESPACE {
|
namespace AB_NAMESPACE {
|
||||||
|
|
||||||
BenchmarkGuard::BenchmarkGuard(const QString &_name)
|
BenchmarkGuard::BenchmarkGuard(const QString &_name)
|
||||||
: name_(_name)
|
: name_(_name)
|
||||||
{
|
{
|
||||||
timer_.start();
|
timer_.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
BenchmarkGuard::~BenchmarkGuard()
|
BenchmarkGuard::~BenchmarkGuard()
|
||||||
{
|
{
|
||||||
log("{} {} ms", this->name_, float(timer_.nsecsElapsed()) / 1000000.0f);
|
log("{} {} ms", this->name_, float(timer_.nsecsElapsed()) / 1000000.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal BenchmarkGuard::getElapsedMs()
|
qreal BenchmarkGuard::getElapsedMs()
|
||||||
{
|
{
|
||||||
return qreal(timer_.nsecsElapsed()) / 1000000.0;
|
return qreal(timer_.nsecsElapsed()) / 1000000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|||||||
+31
-31
@@ -1,31 +1,31 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
|
||||||
#include "ABSettings.hpp"
|
#include "ABSettings.hpp"
|
||||||
#include "ABTheme.hpp"
|
#include "ABTheme.hpp"
|
||||||
#include "singletons/Fonts.hpp"
|
#include "singletons/Fonts.hpp"
|
||||||
#include "widgets/BaseWindow.hpp"
|
#include "widgets/BaseWindow.hpp"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
using namespace AB_NAMESPACE;
|
using namespace AB_NAMESPACE;
|
||||||
|
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
|
|
||||||
auto path =
|
auto path =
|
||||||
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||||
qDebug() << path;
|
qDebug() << path;
|
||||||
|
|
||||||
QDir(path).mkdir(".");
|
QDir(path).mkdir(".");
|
||||||
|
|
||||||
new Settings(path);
|
new Settings(path);
|
||||||
new Fonts();
|
new Fonts();
|
||||||
|
|
||||||
BaseWindow widget(nullptr, BaseWindow::EnableCustomFrame);
|
BaseWindow widget(nullptr, BaseWindow::EnableCustomFrame);
|
||||||
widget.setWindowTitle("asdf");
|
widget.setWindowTitle("asdf");
|
||||||
widget.show();
|
widget.show();
|
||||||
|
|
||||||
return a.exec();
|
return a.exec();
|
||||||
}
|
}
|
||||||
|
|||||||
+100
-100
@@ -1,100 +1,100 @@
|
|||||||
#-------------------------------------------------
|
#-------------------------------------------------
|
||||||
#
|
#
|
||||||
# Project created by QtCreator 2018-11-19T19:03:22
|
# Project created by QtCreator 2018-11-19T19:03:22
|
||||||
#
|
#
|
||||||
#-------------------------------------------------
|
#-------------------------------------------------
|
||||||
|
|
||||||
!AB_NOT_STANDALONE {
|
!AB_NOT_STANDALONE {
|
||||||
message(appbase standalone)
|
message(appbase standalone)
|
||||||
QT += core gui widgets
|
QT += core gui widgets
|
||||||
TARGET = main
|
TARGET = main
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
SOURCES += main.cpp
|
SOURCES += main.cpp
|
||||||
|
|
||||||
# https://bugreports.qt.io/browse/QTBUG-27018
|
# https://bugreports.qt.io/browse/QTBUG-27018
|
||||||
equals(QMAKE_CXX, "clang++")|equals(QMAKE_CXX, "g++") {
|
equals(QMAKE_CXX, "clang++")|equals(QMAKE_CXX, "g++") {
|
||||||
TARGET = bin/appbase
|
TARGET = bin/appbase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#DEFINES += QT_DEPRECATED_WARNINGS
|
#DEFINES += QT_DEPRECATED_WARNINGS
|
||||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000
|
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000
|
||||||
|
|
||||||
macx {
|
macx {
|
||||||
# osx (Tested on macOS Mojave and High Sierra)
|
# osx (Tested on macOS Mojave and High Sierra)
|
||||||
CONFIG += c++17
|
CONFIG += c++17
|
||||||
} else {
|
} else {
|
||||||
CONFIG += c++17
|
CONFIG += c++17
|
||||||
win32-msvc* {
|
win32-msvc* {
|
||||||
# win32 msvc
|
# win32 msvc
|
||||||
QMAKE_CXXFLAGS += /std:c++17
|
QMAKE_CXXFLAGS += /std:c++17
|
||||||
} else {
|
} else {
|
||||||
# clang/gcc on linux or win32
|
# clang/gcc on linux or win32
|
||||||
QMAKE_CXXFLAGS += -std=c++17
|
QMAKE_CXXFLAGS += -std=c++17
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug {
|
debug {
|
||||||
DEFINES += QT_DEBUG
|
DEFINES += QT_DEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
linux {
|
linux {
|
||||||
LIBS += -lrt
|
LIBS += -lrt
|
||||||
QMAKE_LFLAGS += -lrt
|
QMAKE_LFLAGS += -lrt
|
||||||
}
|
}
|
||||||
|
|
||||||
macx {
|
macx {
|
||||||
INCLUDEPATH += /usr/local/include
|
INCLUDEPATH += /usr/local/include
|
||||||
INCLUDEPATH += /usr/local/opt/openssl/include
|
INCLUDEPATH += /usr/local/opt/openssl/include
|
||||||
LIBS += -L/usr/local/opt/openssl/lib
|
LIBS += -L/usr/local/opt/openssl/lib
|
||||||
}
|
}
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/BaseSettings.cpp \
|
$$PWD/BaseSettings.cpp \
|
||||||
$$PWD/BaseTheme.cpp \
|
$$PWD/BaseTheme.cpp \
|
||||||
$$PWD/common/ChatterinoSetting.cpp \
|
$$PWD/common/ChatterinoSetting.cpp \
|
||||||
$$PWD/debug/Benchmark.cpp \
|
$$PWD/debug/Benchmark.cpp \
|
||||||
$$PWD/singletons/Fonts.cpp \
|
$$PWD/singletons/Fonts.cpp \
|
||||||
$$PWD/util/FunctionEventFilter.cpp \
|
$$PWD/util/FunctionEventFilter.cpp \
|
||||||
$$PWD/util/FuzzyConvert.cpp \
|
$$PWD/util/FuzzyConvert.cpp \
|
||||||
$$PWD/util/Helpers.cpp \
|
$$PWD/util/Helpers.cpp \
|
||||||
$$PWD/util/WindowsHelper.cpp \
|
$$PWD/util/WindowsHelper.cpp \
|
||||||
$$PWD/widgets/BaseWidget.cpp \
|
$$PWD/widgets/BaseWidget.cpp \
|
||||||
$$PWD/widgets/BaseWindow.cpp \
|
$$PWD/widgets/BaseWindow.cpp \
|
||||||
$$PWD/widgets/Label.cpp \
|
$$PWD/widgets/Label.cpp \
|
||||||
$$PWD/widgets/TooltipWidget.cpp \
|
$$PWD/widgets/TooltipWidget.cpp \
|
||||||
$$PWD/widgets/helper/Button.cpp \
|
$$PWD/widgets/helper/Button.cpp \
|
||||||
$$PWD/widgets/helper/EffectLabel.cpp \
|
$$PWD/widgets/helper/EffectLabel.cpp \
|
||||||
$$PWD/widgets/helper/SignalLabel.cpp \
|
$$PWD/widgets/helper/SignalLabel.cpp \
|
||||||
$$PWD/widgets/helper/TitlebarButton.cpp \
|
$$PWD/widgets/helper/TitlebarButton.cpp \
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
$$PWD/BaseSettings.hpp \
|
$$PWD/BaseSettings.hpp \
|
||||||
$$PWD/BaseTheme.hpp \
|
$$PWD/BaseTheme.hpp \
|
||||||
$$PWD/common/ChatterinoSetting.hpp \
|
$$PWD/common/ChatterinoSetting.hpp \
|
||||||
$$PWD/common/FlagsEnum.hpp \
|
$$PWD/common/FlagsEnum.hpp \
|
||||||
$$PWD/common/Outcome.hpp \
|
$$PWD/common/Outcome.hpp \
|
||||||
$$PWD/common/Singleton.hpp \
|
$$PWD/common/Singleton.hpp \
|
||||||
$$PWD/debug/AssertInGuiThread.hpp \
|
$$PWD/debug/AssertInGuiThread.hpp \
|
||||||
$$PWD/debug/Benchmark.hpp \
|
$$PWD/debug/Benchmark.hpp \
|
||||||
$$PWD/debug/Log.hpp \
|
$$PWD/debug/Log.hpp \
|
||||||
$$PWD/singletons/Fonts.hpp \
|
$$PWD/singletons/Fonts.hpp \
|
||||||
$$PWD/util/Clamp.hpp \
|
$$PWD/util/Clamp.hpp \
|
||||||
$$PWD/util/CombinePath.hpp \
|
$$PWD/util/CombinePath.hpp \
|
||||||
$$PWD/util/DistanceBetweenPoints.hpp \
|
$$PWD/util/DistanceBetweenPoints.hpp \
|
||||||
$$PWD/util/FunctionEventFilter.hpp \
|
$$PWD/util/FunctionEventFilter.hpp \
|
||||||
$$PWD/util/FuzzyConvert.hpp \
|
$$PWD/util/FuzzyConvert.hpp \
|
||||||
$$PWD/util/Helpers.hpp \
|
$$PWD/util/Helpers.hpp \
|
||||||
$$PWD/util/LayoutHelper.hpp \
|
$$PWD/util/LayoutHelper.hpp \
|
||||||
$$PWD/util/PostToThread.hpp \
|
$$PWD/util/PostToThread.hpp \
|
||||||
$$PWD/util/RapidJsonSerializeQString.hpp \
|
$$PWD/util/RapidJsonSerializeQString.hpp \
|
||||||
$$PWD/util/Shortcut.hpp \
|
$$PWD/util/Shortcut.hpp \
|
||||||
$$PWD/util/WindowsHelper.hpp \
|
$$PWD/util/WindowsHelper.hpp \
|
||||||
$$PWD/widgets/BaseWidget.hpp \
|
$$PWD/widgets/BaseWidget.hpp \
|
||||||
$$PWD/widgets/BaseWindow.hpp \
|
$$PWD/widgets/BaseWindow.hpp \
|
||||||
$$PWD/widgets/Label.hpp \
|
$$PWD/widgets/Label.hpp \
|
||||||
$$PWD/widgets/TooltipWidget.hpp \
|
$$PWD/widgets/TooltipWidget.hpp \
|
||||||
$$PWD/widgets/helper/Button.hpp \
|
$$PWD/widgets/helper/Button.hpp \
|
||||||
$$PWD/widgets/helper/EffectLabel.hpp \
|
$$PWD/widgets/helper/EffectLabel.hpp \
|
||||||
$$PWD/widgets/helper/SignalLabel.hpp \
|
$$PWD/widgets/helper/SignalLabel.hpp \
|
||||||
$$PWD/widgets/helper/TitlebarButton.hpp \
|
$$PWD/widgets/helper/TitlebarButton.hpp \
|
||||||
|
|||||||
+13
-13
@@ -1,13 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace AB_NAMESPACE {
|
namespace AB_NAMESPACE {
|
||||||
|
|
||||||
// http://en.cppreference.com/w/cpp/algorithm/clamp
|
// http://en.cppreference.com/w/cpp/algorithm/clamp
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr const T &clamp(const T &v, const T &lo, const T &hi)
|
constexpr const T &clamp(const T &v, const T &lo, const T &hi)
|
||||||
{
|
{
|
||||||
return assert(!(hi < lo)), (v < lo) ? lo : (hi < v) ? hi : v;
|
return assert(!(hi < lo)), (v < lo) ? lo : (hi < v) ? hi : v;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
// https://stackoverflow.com/a/13014491
|
// https://stackoverflow.com/a/13014491
|
||||||
inline QString combinePath(const QString &a, const QString &b)
|
inline QString combinePath(const QString &a, const QString &b)
|
||||||
{
|
{
|
||||||
return QDir::cleanPath(a + QDir::separator() + b);
|
return QDir::cleanPath(a + QDir::separator() + b);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
#include "FunctionEventFilter.hpp"
|
#include "FunctionEventFilter.hpp"
|
||||||
|
|
||||||
namespace AB_NAMESPACE {
|
namespace AB_NAMESPACE {
|
||||||
|
|
||||||
FunctionEventFilter::FunctionEventFilter(
|
FunctionEventFilter::FunctionEventFilter(
|
||||||
QObject *parent, std::function<bool(QObject *, QEvent *)> function)
|
QObject *parent, std::function<bool(QObject *, QEvent *)> function)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, function_(std::move(function))
|
, function_(std::move(function))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FunctionEventFilter::eventFilter(QObject *watched, QEvent *event)
|
bool FunctionEventFilter::eventFilter(QObject *watched, QEvent *event)
|
||||||
{
|
{
|
||||||
return this->function_(watched, event);
|
return this->function_(watched, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
namespace AB_NAMESPACE {
|
namespace AB_NAMESPACE {
|
||||||
|
|
||||||
class FunctionEventFilter : public QObject
|
class FunctionEventFilter : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FunctionEventFilter(QObject *parent,
|
FunctionEventFilter(QObject *parent,
|
||||||
std::function<bool(QObject *, QEvent *)> function);
|
std::function<bool(QObject *, QEvent *)> function);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::function<bool(QObject *, QEvent *)> function_;
|
std::function<bool(QObject *, QEvent *)> function_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
#include "FuzzyConvert.hpp"
|
#include "FuzzyConvert.hpp"
|
||||||
|
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
int fuzzyToInt(const QString &str, int default_)
|
int fuzzyToInt(const QString &str, int default_)
|
||||||
{
|
{
|
||||||
static auto intFinder = QRegularExpression("[0-9]+");
|
static auto intFinder = QRegularExpression("[0-9]+");
|
||||||
|
|
||||||
auto match = intFinder.match(str);
|
auto match = intFinder.match(str);
|
||||||
if (match.hasMatch())
|
if (match.hasMatch())
|
||||||
{
|
{
|
||||||
return match.captured().toInt();
|
return match.captured().toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
return default_;
|
return default_;
|
||||||
}
|
}
|
||||||
|
|
||||||
float fuzzyToFloat(const QString &str, float default_)
|
float fuzzyToFloat(const QString &str, float default_)
|
||||||
{
|
{
|
||||||
static auto floatFinder = QRegularExpression("[0-9]+(\\.[0-9]+)?");
|
static auto floatFinder = QRegularExpression("[0-9]+(\\.[0-9]+)?");
|
||||||
|
|
||||||
auto match = floatFinder.match(str);
|
auto match = floatFinder.match(str);
|
||||||
if (match.hasMatch())
|
if (match.hasMatch())
|
||||||
{
|
{
|
||||||
return match.captured().toFloat();
|
return match.captured().toFloat();
|
||||||
}
|
}
|
||||||
|
|
||||||
return default_;
|
return default_;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
int fuzzyToInt(const QString &str, int default_);
|
int fuzzyToInt(const QString &str, int default_);
|
||||||
float fuzzyToFloat(const QString &str, float default_);
|
float fuzzyToFloat(const QString &str, float default_);
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,42 +1,42 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QLayout>
|
#include <QLayout>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <boost/variant.hpp>
|
#include <boost/variant.hpp>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
using LayoutItem = boost::variant<QWidget *, QLayout *>;
|
using LayoutItem = boost::variant<QWidget *, QLayout *>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T *makeLayout(std::initializer_list<LayoutItem> items)
|
T *makeLayout(std::initializer_list<LayoutItem> items)
|
||||||
{
|
{
|
||||||
auto t = new T;
|
auto t = new T;
|
||||||
|
|
||||||
for (auto &item : items)
|
for (auto &item : items)
|
||||||
{
|
{
|
||||||
switch (item.which())
|
switch (item.which())
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
t->addItem(new QWidgetItem(boost::get<QWidget *>(item)));
|
t->addItem(new QWidgetItem(boost::get<QWidget *>(item)));
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
t->addItem(boost::get<QLayout *>(item));
|
t->addItem(boost::get<QLayout *>(item));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename With>
|
template <typename T, typename With>
|
||||||
T *makeWidget(With with)
|
T *makeWidget(With with)
|
||||||
{
|
{
|
||||||
auto t = new T;
|
auto t = new T;
|
||||||
|
|
||||||
with(t);
|
with(t);
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,86 +1,86 @@
|
|||||||
#include "WindowsHelper.hpp"
|
#include "WindowsHelper.hpp"
|
||||||
|
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
|
||||||
#ifdef USEWINSDK
|
#ifdef USEWINSDK
|
||||||
|
|
||||||
namespace AB_NAMESPACE {
|
namespace AB_NAMESPACE {
|
||||||
|
|
||||||
typedef enum MONITOR_DPI_TYPE {
|
typedef enum MONITOR_DPI_TYPE {
|
||||||
MDT_EFFECTIVE_DPI = 0,
|
MDT_EFFECTIVE_DPI = 0,
|
||||||
MDT_ANGULAR_DPI = 1,
|
MDT_ANGULAR_DPI = 1,
|
||||||
MDT_RAW_DPI = 2,
|
MDT_RAW_DPI = 2,
|
||||||
MDT_DEFAULT = MDT_EFFECTIVE_DPI
|
MDT_DEFAULT = MDT_EFFECTIVE_DPI
|
||||||
} MONITOR_DPI_TYPE;
|
} MONITOR_DPI_TYPE;
|
||||||
|
|
||||||
typedef HRESULT(CALLBACK *GetDpiForMonitor_)(HMONITOR, MONITOR_DPI_TYPE, UINT *,
|
typedef HRESULT(CALLBACK *GetDpiForMonitor_)(HMONITOR, MONITOR_DPI_TYPE, UINT *,
|
||||||
UINT *);
|
UINT *);
|
||||||
|
|
||||||
boost::optional<UINT> getWindowDpi(HWND hwnd)
|
boost::optional<UINT> getWindowDpi(HWND hwnd)
|
||||||
{
|
{
|
||||||
static HINSTANCE shcore = LoadLibrary(L"Shcore.dll");
|
static HINSTANCE shcore = LoadLibrary(L"Shcore.dll");
|
||||||
if (shcore != nullptr)
|
if (shcore != nullptr)
|
||||||
{
|
{
|
||||||
if (auto getDpiForMonitor =
|
if (auto getDpiForMonitor =
|
||||||
GetDpiForMonitor_(GetProcAddress(shcore, "GetDpiForMonitor")))
|
GetDpiForMonitor_(GetProcAddress(shcore, "GetDpiForMonitor")))
|
||||||
{
|
{
|
||||||
HMONITOR monitor =
|
HMONITOR monitor =
|
||||||
MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
||||||
|
|
||||||
UINT xScale, yScale;
|
UINT xScale, yScale;
|
||||||
|
|
||||||
getDpiForMonitor(monitor, MDT_DEFAULT, &xScale, &yScale);
|
getDpiForMonitor(monitor, MDT_DEFAULT, &xScale, &yScale);
|
||||||
|
|
||||||
return xScale;
|
return xScale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return boost::none;
|
return boost::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef HRESULT(CALLBACK *OleFlushClipboard_)();
|
typedef HRESULT(CALLBACK *OleFlushClipboard_)();
|
||||||
|
|
||||||
void flushClipboard()
|
void flushClipboard()
|
||||||
{
|
{
|
||||||
static HINSTANCE ole32 = LoadLibrary(L"Ole32.dll");
|
static HINSTANCE ole32 = LoadLibrary(L"Ole32.dll");
|
||||||
if (ole32 != nullptr)
|
if (ole32 != nullptr)
|
||||||
{
|
{
|
||||||
if (auto oleFlushClipboard =
|
if (auto oleFlushClipboard =
|
||||||
OleFlushClipboard_(GetProcAddress(ole32, "OleFlushClipboard")))
|
OleFlushClipboard_(GetProcAddress(ole32, "OleFlushClipboard")))
|
||||||
{
|
{
|
||||||
oleFlushClipboard();
|
oleFlushClipboard();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr const char *runKey =
|
constexpr const char *runKey =
|
||||||
"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run";
|
"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run";
|
||||||
|
|
||||||
bool isRegisteredForStartup()
|
bool isRegisteredForStartup()
|
||||||
{
|
{
|
||||||
QSettings settings(runKey, QSettings::NativeFormat);
|
QSettings settings(runKey, QSettings::NativeFormat);
|
||||||
|
|
||||||
return !settings.value("Chatterino").toString().isEmpty();
|
return !settings.value("Chatterino").toString().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRegisteredForStartup(bool isRegistered)
|
void setRegisteredForStartup(bool isRegistered)
|
||||||
{
|
{
|
||||||
QSettings settings(runKey, QSettings::NativeFormat);
|
QSettings settings(runKey, QSettings::NativeFormat);
|
||||||
|
|
||||||
if (isRegistered)
|
if (isRegistered)
|
||||||
{
|
{
|
||||||
auto exePath = QFileInfo(QCoreApplication::applicationFilePath())
|
auto exePath = QFileInfo(QCoreApplication::applicationFilePath())
|
||||||
.absoluteFilePath()
|
.absoluteFilePath()
|
||||||
.replace('/', '\\');
|
.replace('/', '\\');
|
||||||
|
|
||||||
settings.setValue("Chatterino", "\"" + exePath + "\" --autorun");
|
settings.setValue("Chatterino", "\"" + exePath + "\" --autorun");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
settings.remove("Chatterino");
|
settings.remove("Chatterino");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef USEWINSDK
|
#ifdef USEWINSDK
|
||||||
|
|
||||||
# include <Windows.h>
|
# include <Windows.h>
|
||||||
# include <boost/optional.hpp>
|
# include <boost/optional.hpp>
|
||||||
|
|
||||||
namespace AB_NAMESPACE {
|
namespace AB_NAMESPACE {
|
||||||
|
|
||||||
boost::optional<UINT> getWindowDpi(HWND hwnd);
|
boost::optional<UINT> getWindowDpi(HWND hwnd);
|
||||||
void flushClipboard();
|
void flushClipboard();
|
||||||
|
|
||||||
bool isRegisteredForStartup();
|
bool isRegisteredForStartup();
|
||||||
void setRegisteredForStartup(bool isRegistered);
|
void setRegisteredForStartup(bool isRegistered);
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+1000
-990
File diff suppressed because it is too large
Load Diff
+138
-135
@@ -1,135 +1,138 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "widgets/BaseWidget.hpp"
|
#include "widgets/BaseWidget.hpp"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <pajlada/signals/signalholder.hpp>
|
#include <pajlada/signals/signalholder.hpp>
|
||||||
|
#include "common/FlagsEnum.hpp"
|
||||||
class QHBoxLayout;
|
|
||||||
struct tagMSG;
|
class QHBoxLayout;
|
||||||
typedef struct tagMSG MSG;
|
struct tagMSG;
|
||||||
|
typedef struct tagMSG MSG;
|
||||||
namespace AB_NAMESPACE {
|
|
||||||
|
namespace AB_NAMESPACE {
|
||||||
class Button;
|
|
||||||
class EffectLabel;
|
class Button;
|
||||||
class TitleBarButton;
|
class EffectLabel;
|
||||||
enum class TitleBarButtonStyle;
|
class TitleBarButton;
|
||||||
|
enum class TitleBarButtonStyle;
|
||||||
class BaseWindow : public BaseWidget
|
|
||||||
{
|
class BaseWindow : public BaseWidget
|
||||||
Q_OBJECT
|
{
|
||||||
|
Q_OBJECT
|
||||||
public:
|
|
||||||
enum Flags {
|
public:
|
||||||
None = 0,
|
enum Flags {
|
||||||
EnableCustomFrame = 1,
|
None = 0,
|
||||||
Frameless = 2,
|
EnableCustomFrame = 1,
|
||||||
TopMost = 4,
|
Frameless = 2,
|
||||||
DisableCustomScaling = 8,
|
TopMost = 4,
|
||||||
FramelessDraggable = 16,
|
DisableCustomScaling = 8,
|
||||||
};
|
FramelessDraggable = 16,
|
||||||
|
};
|
||||||
enum ActionOnFocusLoss { Nothing, Delete, Close, Hide };
|
|
||||||
|
enum ActionOnFocusLoss { Nothing, Delete, Close, Hide };
|
||||||
explicit BaseWindow(QWidget *parent = nullptr, Flags flags_ = None);
|
|
||||||
|
explicit BaseWindow(FlagsEnum<Flags> flags_ = None,
|
||||||
void setInitialBounds(const QRect &bounds);
|
QWidget *parent = nullptr);
|
||||||
QRect getBounds();
|
|
||||||
|
void setInitialBounds(const QRect &bounds);
|
||||||
QWidget *getLayoutContainer();
|
QRect getBounds();
|
||||||
bool hasCustomWindowFrame();
|
|
||||||
TitleBarButton *addTitleBarButton(const TitleBarButtonStyle &style,
|
QWidget *getLayoutContainer();
|
||||||
std::function<void()> onClicked);
|
bool hasCustomWindowFrame();
|
||||||
EffectLabel *addTitleBarLabel(std::function<void()> onClicked);
|
TitleBarButton *addTitleBarButton(const TitleBarButtonStyle &style,
|
||||||
|
std::function<void()> onClicked);
|
||||||
void setStayInScreenRect(bool value);
|
EffectLabel *addTitleBarLabel(std::function<void()> onClicked);
|
||||||
bool getStayInScreenRect() const;
|
|
||||||
|
void setStayInScreenRect(bool value);
|
||||||
void setActionOnFocusLoss(ActionOnFocusLoss value);
|
bool getStayInScreenRect() const;
|
||||||
ActionOnFocusLoss getActionOnFocusLoss() const;
|
|
||||||
|
void setActionOnFocusLoss(ActionOnFocusLoss value);
|
||||||
void moveTo(QWidget *widget, QPoint point, bool offset = true);
|
ActionOnFocusLoss getActionOnFocusLoss() const;
|
||||||
|
|
||||||
virtual float scale() const override;
|
void moveTo(QWidget *widget, QPoint point, bool offset = true);
|
||||||
float qtFontScale() const;
|
|
||||||
|
virtual float scale() const override;
|
||||||
Flags getFlags();
|
float qtFontScale() const;
|
||||||
|
|
||||||
pajlada::Signals::NoArgSignal closing;
|
pajlada::Signals::NoArgSignal closing;
|
||||||
|
|
||||||
static bool supportsCustomWindowFrame();
|
static bool supportsCustomWindowFrame();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool nativeEvent(const QByteArray &eventType, void *message,
|
virtual bool nativeEvent(const QByteArray &eventType, void *message,
|
||||||
long *result) override;
|
long *result) override;
|
||||||
virtual void scaleChangedEvent(float) override;
|
virtual void scaleChangedEvent(float) override;
|
||||||
|
|
||||||
virtual void paintEvent(QPaintEvent *) override;
|
virtual void paintEvent(QPaintEvent *) override;
|
||||||
|
|
||||||
virtual void changeEvent(QEvent *) override;
|
virtual void changeEvent(QEvent *) override;
|
||||||
virtual void leaveEvent(QEvent *) override;
|
virtual void leaveEvent(QEvent *) override;
|
||||||
virtual void resizeEvent(QResizeEvent *) override;
|
virtual void resizeEvent(QResizeEvent *) override;
|
||||||
virtual void moveEvent(QMoveEvent *) override;
|
virtual void moveEvent(QMoveEvent *) override;
|
||||||
virtual void closeEvent(QCloseEvent *) override;
|
virtual void closeEvent(QCloseEvent *) override;
|
||||||
|
virtual void showEvent(QShowEvent *) override;
|
||||||
virtual void themeChangedEvent() override;
|
|
||||||
virtual bool event(QEvent *event) override;
|
virtual void themeChangedEvent() override;
|
||||||
virtual void wheelEvent(QWheelEvent *event) override;
|
virtual bool event(QEvent *event) override;
|
||||||
|
virtual void wheelEvent(QWheelEvent *event) override;
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
|
||||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
void mouseMoveEvent(QMouseEvent *event) override;
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||||
QPointF movingRelativePos;
|
void mouseMoveEvent(QMouseEvent *event) override;
|
||||||
bool moving{};
|
QPointF movingRelativePos;
|
||||||
|
bool moving{};
|
||||||
void updateScale();
|
|
||||||
|
void updateScale();
|
||||||
boost::optional<QColor> overrideBackgroundColor_;
|
|
||||||
|
boost::optional<QColor> overrideBackgroundColor_;
|
||||||
private:
|
|
||||||
void init();
|
private:
|
||||||
void moveIntoDesktopRect(QWidget *parent);
|
void init();
|
||||||
void calcButtonsSizes();
|
void moveIntoDesktopRect(QWidget *parent);
|
||||||
void drawCustomWindowFrame(QPainter &painter);
|
void calcButtonsSizes();
|
||||||
void onFocusLost();
|
void drawCustomWindowFrame(QPainter &painter);
|
||||||
|
void onFocusLost();
|
||||||
bool handleDPICHANGED(MSG *msg);
|
|
||||||
bool handleSHOWWINDOW(MSG *msg);
|
bool handleDPICHANGED(MSG *msg);
|
||||||
bool handleNCCALCSIZE(MSG *msg, long *result);
|
bool handleSHOWWINDOW(MSG *msg);
|
||||||
bool handleSIZE(MSG *msg);
|
bool handleNCCALCSIZE(MSG *msg, long *result);
|
||||||
bool handleMOVE(MSG *msg);
|
bool handleSIZE(MSG *msg);
|
||||||
bool handleNCHITTEST(MSG *msg, long *result);
|
bool handleMOVE(MSG *msg);
|
||||||
|
bool handleNCHITTEST(MSG *msg, long *result);
|
||||||
bool enableCustomFrame_;
|
|
||||||
ActionOnFocusLoss actionOnFocusLoss_ = Nothing;
|
bool enableCustomFrame_;
|
||||||
bool frameless_;
|
ActionOnFocusLoss actionOnFocusLoss_ = Nothing;
|
||||||
bool stayInScreenRect_ = false;
|
bool frameless_;
|
||||||
bool shown_ = false;
|
bool stayInScreenRect_ = false;
|
||||||
Flags flags_;
|
bool shown_ = false;
|
||||||
float nativeScale_ = 1;
|
FlagsEnum<Flags> flags_;
|
||||||
|
float nativeScale_ = 1;
|
||||||
struct {
|
|
||||||
QLayout *windowLayout = nullptr;
|
struct {
|
||||||
QHBoxLayout *titlebarBox = nullptr;
|
QLayout *windowLayout = nullptr;
|
||||||
QWidget *titleLabel = nullptr;
|
QHBoxLayout *titlebarBox = nullptr;
|
||||||
TitleBarButton *minButton = nullptr;
|
QWidget *titleLabel = nullptr;
|
||||||
TitleBarButton *maxButton = nullptr;
|
TitleBarButton *minButton = nullptr;
|
||||||
TitleBarButton *exitButton = nullptr;
|
TitleBarButton *maxButton = nullptr;
|
||||||
QWidget *layoutBase = nullptr;
|
TitleBarButton *exitButton = nullptr;
|
||||||
std::vector<Button *> buttons;
|
QWidget *layoutBase = nullptr;
|
||||||
} ui_;
|
std::vector<Button *> buttons;
|
||||||
|
} ui_;
|
||||||
#ifdef USEWINSDK
|
|
||||||
QRect initalBounds_;
|
#ifdef USEWINSDK
|
||||||
QRect currentBounds_;
|
QRect initalBounds_;
|
||||||
bool isNotMinimizedOrMaximized_{};
|
QRect currentBounds_;
|
||||||
#endif
|
QRect nextBounds_;
|
||||||
|
QTimer useNextBounds_;
|
||||||
pajlada::Signals::SignalHolder connections_;
|
bool isNotMinimizedOrMaximized_{};
|
||||||
std::vector<pajlada::Signals::ScopedConnection> managedConnections_;
|
#endif
|
||||||
|
|
||||||
friend class BaseWidget;
|
pajlada::Signals::SignalHolder connections_;
|
||||||
};
|
std::vector<pajlada::Signals::ScopedConnection> managedConnections_;
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
friend class BaseWidget;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace AB_NAMESPACE
|
||||||
|
|||||||
+132
-132
@@ -1,132 +1,132 @@
|
|||||||
#include "Label.hpp"
|
#include "Label.hpp"
|
||||||
|
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|
||||||
namespace AB_NAMESPACE {
|
namespace AB_NAMESPACE {
|
||||||
|
|
||||||
Label::Label(QString text, FontStyle style)
|
Label::Label(QString text, FontStyle style)
|
||||||
: Label(nullptr, text, style)
|
: Label(nullptr, text, style)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Label::Label(BaseWidget *parent, QString text, FontStyle style)
|
Label::Label(BaseWidget *parent, QString text, FontStyle style)
|
||||||
: BaseWidget(parent)
|
: BaseWidget(parent)
|
||||||
, text_(text)
|
, text_(text)
|
||||||
, fontStyle_(style)
|
, fontStyle_(style)
|
||||||
{
|
{
|
||||||
this->connections_.managedConnect(getFonts()->fontChanged,
|
this->connections_.managedConnect(getFonts()->fontChanged,
|
||||||
[this] { this->updateSize(); });
|
[this] { this->updateSize(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString &Label::getText() const
|
const QString &Label::getText() const
|
||||||
{
|
{
|
||||||
return this->text_;
|
return this->text_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Label::setText(const QString &text)
|
void Label::setText(const QString &text)
|
||||||
{
|
{
|
||||||
if (this->text_ != text)
|
if (this->text_ != text)
|
||||||
{
|
{
|
||||||
this->text_ = text;
|
this->text_ = text;
|
||||||
this->updateSize();
|
this->updateSize();
|
||||||
this->update();
|
this->update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FontStyle Label::getFontStyle() const
|
FontStyle Label::getFontStyle() const
|
||||||
{
|
{
|
||||||
return this->fontStyle_;
|
return this->fontStyle_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Label::getCentered() const
|
bool Label::getCentered() const
|
||||||
{
|
{
|
||||||
return this->centered_;
|
return this->centered_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Label::setCentered(bool centered)
|
void Label::setCentered(bool centered)
|
||||||
{
|
{
|
||||||
this->centered_ = centered;
|
this->centered_ = centered;
|
||||||
this->updateSize();
|
this->updateSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Label::getHasOffset() const
|
bool Label::getHasOffset() const
|
||||||
{
|
{
|
||||||
return this->hasOffset_;
|
return this->hasOffset_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Label::setHasOffset(bool hasOffset)
|
void Label::setHasOffset(bool hasOffset)
|
||||||
{
|
{
|
||||||
this->hasOffset_ = hasOffset;
|
this->hasOffset_ = hasOffset;
|
||||||
this->updateSize();
|
this->updateSize();
|
||||||
}
|
}
|
||||||
void Label::setFontStyle(FontStyle style)
|
void Label::setFontStyle(FontStyle style)
|
||||||
{
|
{
|
||||||
this->fontStyle_ = style;
|
this->fontStyle_ = style;
|
||||||
this->updateSize();
|
this->updateSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Label::scaleChangedEvent(float scale)
|
void Label::scaleChangedEvent(float scale)
|
||||||
{
|
{
|
||||||
this->updateSize();
|
this->updateSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize Label::sizeHint() const
|
QSize Label::sizeHint() const
|
||||||
{
|
{
|
||||||
return this->preferedSize_;
|
return this->preferedSize_;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize Label::minimumSizeHint() const
|
QSize Label::minimumSizeHint() const
|
||||||
{
|
{
|
||||||
return this->preferedSize_;
|
return this->preferedSize_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Label::paintEvent(QPaintEvent *)
|
void Label::paintEvent(QPaintEvent *)
|
||||||
{
|
{
|
||||||
QPainter painter(this);
|
QPainter painter(this);
|
||||||
QFontMetrics metrics = getFonts()->getFontMetrics(
|
QFontMetrics metrics = getFonts()->getFontMetrics(
|
||||||
this->getFontStyle(),
|
this->getFontStyle(),
|
||||||
this->scale() * 96.f / this->logicalDpiX() * this->devicePixelRatioF());
|
this->scale() * 96.f / this->logicalDpiX() * this->devicePixelRatioF());
|
||||||
painter.setFont(getFonts()->getFont(
|
painter.setFont(getFonts()->getFont(
|
||||||
this->getFontStyle(), this->scale() * 96.f / this->logicalDpiX() *
|
this->getFontStyle(), this->scale() * 96.f / this->logicalDpiX() *
|
||||||
this->devicePixelRatioF()));
|
this->devicePixelRatioF()));
|
||||||
|
|
||||||
int offset = this->getOffset();
|
int offset = this->getOffset();
|
||||||
|
|
||||||
// draw text
|
// draw text
|
||||||
QRect textRect(offset, 0, this->width() - offset - offset, this->height());
|
QRect textRect(offset, 0, this->width() - offset - offset, this->height());
|
||||||
|
|
||||||
int width = metrics.width(this->text_);
|
int width = metrics.width(this->text_);
|
||||||
Qt::Alignment alignment = !this->centered_ || width > textRect.width()
|
Qt::Alignment alignment = !this->centered_ || width > textRect.width()
|
||||||
? Qt::AlignLeft | Qt::AlignVCenter
|
? Qt::AlignLeft | Qt::AlignVCenter
|
||||||
: Qt::AlignCenter;
|
: Qt::AlignCenter;
|
||||||
|
|
||||||
painter.setBrush(this->palette().windowText());
|
painter.setBrush(this->palette().windowText());
|
||||||
|
|
||||||
QTextOption option(alignment);
|
QTextOption option(alignment);
|
||||||
option.setWrapMode(QTextOption::NoWrap);
|
option.setWrapMode(QTextOption::NoWrap);
|
||||||
painter.drawText(textRect, this->text_, option);
|
painter.drawText(textRect, this->text_, option);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
painter.setPen(QColor(255, 0, 0));
|
painter.setPen(QColor(255, 0, 0));
|
||||||
painter.drawRect(0, 0, this->width() - 1, this->height() - 1);
|
painter.drawRect(0, 0, this->width() - 1, this->height() - 1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Label::updateSize()
|
void Label::updateSize()
|
||||||
{
|
{
|
||||||
QFontMetrics metrics =
|
QFontMetrics metrics =
|
||||||
getFonts()->getFontMetrics(this->fontStyle_, this->scale());
|
getFonts()->getFontMetrics(this->fontStyle_, this->scale());
|
||||||
|
|
||||||
int width = metrics.width(this->text_) + (2 * this->getOffset());
|
int width = metrics.width(this->text_) + (2 * this->getOffset());
|
||||||
int height = metrics.height();
|
int height = metrics.height();
|
||||||
this->preferedSize_ = QSize(width, height);
|
this->preferedSize_ = QSize(width, height);
|
||||||
|
|
||||||
this->updateGeometry();
|
this->updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Label::getOffset()
|
int Label::getOffset()
|
||||||
{
|
{
|
||||||
return this->hasOffset_ ? int(8 * this->scale()) : 0;
|
return this->hasOffset_ ? int(8 * this->scale()) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|||||||
@@ -1,50 +1,50 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "singletons/Fonts.hpp"
|
#include "singletons/Fonts.hpp"
|
||||||
#include "widgets/BaseWidget.hpp"
|
#include "widgets/BaseWidget.hpp"
|
||||||
|
|
||||||
#include <pajlada/signals/signalholder.hpp>
|
#include <pajlada/signals/signalholder.hpp>
|
||||||
|
|
||||||
namespace AB_NAMESPACE {
|
namespace AB_NAMESPACE {
|
||||||
|
|
||||||
class Label : public BaseWidget
|
class Label : public BaseWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Label(QString text = QString(),
|
explicit Label(QString text = QString(),
|
||||||
FontStyle style = FontStyle::UiMedium);
|
FontStyle style = FontStyle::UiMedium);
|
||||||
explicit Label(BaseWidget *parent, QString text = QString(),
|
explicit Label(BaseWidget *parent, QString text = QString(),
|
||||||
FontStyle style = FontStyle::UiMedium);
|
FontStyle style = FontStyle::UiMedium);
|
||||||
|
|
||||||
const QString &getText() const;
|
const QString &getText() const;
|
||||||
void setText(const QString &text);
|
void setText(const QString &text);
|
||||||
|
|
||||||
FontStyle getFontStyle() const;
|
FontStyle getFontStyle() const;
|
||||||
void setFontStyle(FontStyle style);
|
void setFontStyle(FontStyle style);
|
||||||
|
|
||||||
bool getCentered() const;
|
bool getCentered() const;
|
||||||
void setCentered(bool centered);
|
void setCentered(bool centered);
|
||||||
|
|
||||||
bool getHasOffset() const;
|
bool getHasOffset() const;
|
||||||
void setHasOffset(bool hasOffset);
|
void setHasOffset(bool hasOffset);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void scaleChangedEvent(float scale_) override;
|
virtual void scaleChangedEvent(float scale_) override;
|
||||||
virtual void paintEvent(QPaintEvent *) override;
|
virtual void paintEvent(QPaintEvent *) override;
|
||||||
|
|
||||||
virtual QSize sizeHint() const override;
|
virtual QSize sizeHint() const override;
|
||||||
virtual QSize minimumSizeHint() const override;
|
virtual QSize minimumSizeHint() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateSize();
|
void updateSize();
|
||||||
int getOffset();
|
int getOffset();
|
||||||
|
|
||||||
QString text_;
|
QString text_;
|
||||||
FontStyle fontStyle_;
|
FontStyle fontStyle_;
|
||||||
QSize preferedSize_;
|
QSize preferedSize_;
|
||||||
bool centered_ = false;
|
bool centered_ = false;
|
||||||
bool hasOffset_ = true;
|
bool hasOffset_ = true;
|
||||||
|
|
||||||
pajlada::Signals::SignalHolder connections_;
|
pajlada::Signals::SignalHolder connections_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ TooltipWidget *TooltipWidget::getInstance()
|
|||||||
}
|
}
|
||||||
|
|
||||||
TooltipWidget::TooltipWidget(BaseWidget *parent)
|
TooltipWidget::TooltipWidget(BaseWidget *parent)
|
||||||
: BaseWindow(parent, BaseWindow::TopMost)
|
: BaseWindow(BaseWindow::TopMost, parent)
|
||||||
, displayImage_(new QLabel())
|
, displayImage_(new QLabel())
|
||||||
, displayText_(new QLabel())
|
, displayText_(new QLabel())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,134 +1,134 @@
|
|||||||
#include "TitlebarButton.hpp"
|
#include "TitlebarButton.hpp"
|
||||||
|
|
||||||
#include "BaseTheme.hpp"
|
#include "BaseTheme.hpp"
|
||||||
|
|
||||||
namespace AB_NAMESPACE {
|
namespace AB_NAMESPACE {
|
||||||
|
|
||||||
TitleBarButton::TitleBarButton()
|
TitleBarButton::TitleBarButton()
|
||||||
: Button(nullptr)
|
: Button(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TitleBarButtonStyle TitleBarButton::getButtonStyle() const
|
TitleBarButtonStyle TitleBarButton::getButtonStyle() const
|
||||||
{
|
{
|
||||||
return this->style_;
|
return this->style_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TitleBarButton::setButtonStyle(TitleBarButtonStyle _style)
|
void TitleBarButton::setButtonStyle(TitleBarButtonStyle _style)
|
||||||
{
|
{
|
||||||
this->style_ = _style;
|
this->style_ = _style;
|
||||||
this->update();
|
this->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TitleBarButton::paintEvent(QPaintEvent *event)
|
void TitleBarButton::paintEvent(QPaintEvent *event)
|
||||||
{
|
{
|
||||||
QPainter painter(this);
|
QPainter painter(this);
|
||||||
|
|
||||||
painter.setOpacity(this->getCurrentDimAmount());
|
painter.setOpacity(this->getCurrentDimAmount());
|
||||||
|
|
||||||
QColor color = this->theme->window.text;
|
QColor color = this->theme->window.text;
|
||||||
QColor background = this->theme->window.background;
|
QColor background = this->theme->window.background;
|
||||||
|
|
||||||
int xD = this->height() / 3;
|
int xD = this->height() / 3;
|
||||||
int centerX = this->width() / 2;
|
int centerX = this->width() / 2;
|
||||||
|
|
||||||
painter.setRenderHint(QPainter::Antialiasing, false);
|
painter.setRenderHint(QPainter::Antialiasing, false);
|
||||||
|
|
||||||
switch (this->style_)
|
switch (this->style_)
|
||||||
{
|
{
|
||||||
case TitleBarButtonStyle::Minimize:
|
case TitleBarButtonStyle::Minimize:
|
||||||
{
|
{
|
||||||
painter.fillRect(centerX - xD / 2, xD * 3 / 2, xD, 1, color);
|
painter.fillRect(centerX - xD / 2, xD * 3 / 2, xD, 1, color);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TitleBarButtonStyle::Maximize:
|
case TitleBarButtonStyle::Maximize:
|
||||||
{
|
{
|
||||||
painter.setPen(color);
|
painter.setPen(color);
|
||||||
painter.drawRect(centerX - xD / 2, xD, xD - 1, xD - 1);
|
painter.drawRect(centerX - xD / 2, xD, xD - 1, xD - 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TitleBarButtonStyle::Unmaximize:
|
case TitleBarButtonStyle::Unmaximize:
|
||||||
{
|
{
|
||||||
int xD2 = xD * 1 / 5;
|
int xD2 = xD * 1 / 5;
|
||||||
int xD3 = xD * 4 / 5;
|
int xD3 = xD * 4 / 5;
|
||||||
|
|
||||||
painter.drawRect(centerX - xD / 2 + xD2, xD, xD3, xD3);
|
painter.drawRect(centerX - xD / 2 + xD2, xD, xD3, xD3);
|
||||||
painter.fillRect(centerX - xD / 2, xD + xD2, xD3, xD3,
|
painter.fillRect(centerX - xD / 2, xD + xD2, xD3, xD3,
|
||||||
this->theme->window.background);
|
this->theme->window.background);
|
||||||
painter.drawRect(centerX - xD / 2, xD + xD2, xD3, xD3);
|
painter.drawRect(centerX - xD / 2, xD + xD2, xD3, xD3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TitleBarButtonStyle::Close:
|
case TitleBarButtonStyle::Close:
|
||||||
{
|
{
|
||||||
QRect rect(centerX - xD / 2, xD, xD - 1, xD - 1);
|
QRect rect(centerX - xD / 2, xD, xD - 1, xD - 1);
|
||||||
painter.setPen(QPen(color, 1));
|
painter.setPen(QPen(color, 1));
|
||||||
|
|
||||||
painter.drawLine(rect.topLeft(), rect.bottomRight());
|
painter.drawLine(rect.topLeft(), rect.bottomRight());
|
||||||
painter.drawLine(rect.topRight(), rect.bottomLeft());
|
painter.drawLine(rect.topRight(), rect.bottomLeft());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TitleBarButtonStyle::User:
|
case TitleBarButtonStyle::User:
|
||||||
{
|
{
|
||||||
color = "#999";
|
color = "#999";
|
||||||
|
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
painter.setRenderHint(QPainter::HighQualityAntialiasing);
|
painter.setRenderHint(QPainter::HighQualityAntialiasing);
|
||||||
|
|
||||||
auto a = xD / 3;
|
auto a = xD / 3;
|
||||||
QPainterPath path;
|
QPainterPath path;
|
||||||
|
|
||||||
painter.save();
|
painter.save();
|
||||||
painter.translate(3, 3);
|
painter.translate(3, 3);
|
||||||
|
|
||||||
path.arcMoveTo(a, 4 * a, 6 * a, 6 * a, 0);
|
path.arcMoveTo(a, 4 * a, 6 * a, 6 * a, 0);
|
||||||
path.arcTo(a, 4 * a, 6 * a, 6 * a, 0, 180);
|
path.arcTo(a, 4 * a, 6 * a, 6 * a, 0, 180);
|
||||||
|
|
||||||
painter.fillPath(path, color);
|
painter.fillPath(path, color);
|
||||||
|
|
||||||
painter.setBrush(background);
|
painter.setBrush(background);
|
||||||
painter.drawEllipse(2 * a, 1 * a, 4 * a, 4 * a);
|
painter.drawEllipse(2 * a, 1 * a, 4 * a, 4 * a);
|
||||||
|
|
||||||
painter.setBrush(color);
|
painter.setBrush(color);
|
||||||
painter.drawEllipse(2.5 * a, 1.5 * a, 3 * a + 1, 3 * a);
|
painter.drawEllipse(2.5 * a, 1.5 * a, 3 * a + 1, 3 * a);
|
||||||
painter.restore();
|
painter.restore();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TitleBarButtonStyle::Settings:
|
case TitleBarButtonStyle::Settings:
|
||||||
{
|
{
|
||||||
color = "#999";
|
color = "#999";
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
painter.setRenderHint(QPainter::HighQualityAntialiasing);
|
painter.setRenderHint(QPainter::HighQualityAntialiasing);
|
||||||
|
|
||||||
painter.save();
|
painter.save();
|
||||||
painter.translate(3, 3);
|
painter.translate(3, 3);
|
||||||
|
|
||||||
auto a = xD / 3;
|
auto a = xD / 3;
|
||||||
QPainterPath path;
|
QPainterPath path;
|
||||||
|
|
||||||
path.arcMoveTo(a, a, 6 * a, 6 * a, 0 - (360 / 32.0));
|
path.arcMoveTo(a, a, 6 * a, 6 * a, 0 - (360 / 32.0));
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
path.arcTo(a, a, 6 * a, 6 * a, i * (360 / 8.0) - (360 / 32.0),
|
path.arcTo(a, a, 6 * a, 6 * a, i * (360 / 8.0) - (360 / 32.0),
|
||||||
(360 / 32.0));
|
(360 / 32.0));
|
||||||
path.arcTo(2 * a, 2 * a, 4 * a, 4 * a,
|
path.arcTo(2 * a, 2 * a, 4 * a, 4 * a,
|
||||||
i * (360 / 8.0) + (360 / 32.0), (360 / 32.0));
|
i * (360 / 8.0) + (360 / 32.0), (360 / 32.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
painter.strokePath(path, color);
|
painter.strokePath(path, color);
|
||||||
painter.fillPath(path, color);
|
painter.fillPath(path, color);
|
||||||
|
|
||||||
painter.setBrush(background);
|
painter.setBrush(background);
|
||||||
painter.drawEllipse(3 * a, 3 * a, 2 * a, 2 * a);
|
painter.drawEllipse(3 * a, 3 * a, 2 * a, 2 * a);
|
||||||
painter.restore();
|
painter.restore();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
|
|
||||||
Button::paintEvent(event);
|
Button::paintEvent(event);
|
||||||
// this->fancyPaint(painter);
|
// this->fancyPaint(painter);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "widgets/helper/Button.hpp"
|
#include "widgets/helper/Button.hpp"
|
||||||
|
|
||||||
namespace AB_NAMESPACE {
|
namespace AB_NAMESPACE {
|
||||||
|
|
||||||
enum class TitleBarButtonStyle {
|
enum class TitleBarButtonStyle {
|
||||||
None = 0,
|
None = 0,
|
||||||
Minimize = 1,
|
Minimize = 1,
|
||||||
Maximize = 2,
|
Maximize = 2,
|
||||||
Unmaximize = 4,
|
Unmaximize = 4,
|
||||||
Close = 8,
|
Close = 8,
|
||||||
User = 16,
|
User = 16,
|
||||||
Settings = 32
|
Settings = 32
|
||||||
};
|
};
|
||||||
|
|
||||||
class TitleBarButton : public Button
|
class TitleBarButton : public Button
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TitleBarButton();
|
TitleBarButton();
|
||||||
|
|
||||||
TitleBarButtonStyle getButtonStyle() const;
|
TitleBarButtonStyle getButtonStyle() const;
|
||||||
void setButtonStyle(TitleBarButtonStyle style_);
|
void setButtonStyle(TitleBarButtonStyle style_);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *) override;
|
void paintEvent(QPaintEvent *) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TitleBarButtonStyle style_;
|
TitleBarButtonStyle style_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace AB_NAMESPACE
|
} // namespace AB_NAMESPACE
|
||||||
|
|||||||
+1
-1
Submodule lib/websocketpp updated: 19cad9925f...1e0138c7cc
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
class Channel;
|
||||||
|
class ChannelView;
|
||||||
|
using ChannelPtr = std::shared_ptr<Channel>;
|
||||||
|
|
||||||
|
struct Message;
|
||||||
|
using MessagePtr = std::shared_ptr<const Message>;
|
||||||
|
} // namespace chatterino
|
||||||
+170
-168
@@ -1,168 +1,170 @@
|
|||||||
#ifdef __cplusplus
|
#pragma once
|
||||||
# include <fmt/format.h>
|
|
||||||
# include <irccommand.h>
|
#ifdef __cplusplus
|
||||||
# include <ircconnection.h>
|
# include <fmt/format.h>
|
||||||
# include <rapidjson/document.h>
|
# include <irccommand.h>
|
||||||
# include <rapidjson/error/en.h>
|
# include <ircconnection.h>
|
||||||
# include <rapidjson/error/error.h>
|
# include <rapidjson/document.h>
|
||||||
# include <IrcMessage>
|
# include <rapidjson/error/en.h>
|
||||||
# include <QAbstractListModel>
|
# include <rapidjson/error/error.h>
|
||||||
# include <QAbstractNativeEventFilter>
|
# include <IrcMessage>
|
||||||
# include <QAction>
|
# include <QAbstractListModel>
|
||||||
# include <QApplication>
|
# include <QAbstractNativeEventFilter>
|
||||||
# include <QBrush>
|
# include <QAction>
|
||||||
# include <QBuffer>
|
# include <QApplication>
|
||||||
# include <QButtonGroup>
|
# include <QBrush>
|
||||||
# include <QByteArray>
|
# include <QBuffer>
|
||||||
# include <QCheckBox>
|
# include <QButtonGroup>
|
||||||
# include <QClipboard>
|
# include <QByteArray>
|
||||||
# include <QColor>
|
# include <QCheckBox>
|
||||||
# include <QComboBox>
|
# include <QClipboard>
|
||||||
# include <QCompleter>
|
# include <QColor>
|
||||||
# include <QCoreApplication>
|
# include <QComboBox>
|
||||||
# include <QDateTime>
|
# include <QCompleter>
|
||||||
# include <QDebug>
|
# include <QCoreApplication>
|
||||||
# include <QDesktopServices>
|
# include <QDateTime>
|
||||||
# include <QDialog>
|
# include <QDebug>
|
||||||
# include <QDialogButtonBox>
|
# include <QDesktopServices>
|
||||||
# include <QDir>
|
# include <QDialog>
|
||||||
# include <QDockWidget>
|
# include <QDialogButtonBox>
|
||||||
# include <QDrag>
|
# include <QDir>
|
||||||
# include <QDragEnterEvent>
|
# include <QDockWidget>
|
||||||
# include <QElapsedTimer>
|
# include <QDrag>
|
||||||
# include <QEventLoop>
|
# include <QDragEnterEvent>
|
||||||
# include <QFile>
|
# include <QElapsedTimer>
|
||||||
# include <QFileDialog>
|
# include <QEventLoop>
|
||||||
# include <QFileInfo>
|
# include <QFile>
|
||||||
# include <QFlags>
|
# include <QFileDialog>
|
||||||
# include <QFont>
|
# include <QFileInfo>
|
||||||
# include <QFontDatabase>
|
# include <QFlags>
|
||||||
# include <QFontDialog>
|
# include <QFont>
|
||||||
# include <QFontMetrics>
|
# include <QFontDatabase>
|
||||||
# include <QFormLayout>
|
# include <QFontDialog>
|
||||||
# include <QGraphicsBlurEffect>
|
# include <QFontMetrics>
|
||||||
# include <QGroupBox>
|
# include <QFormLayout>
|
||||||
# include <QHBoxLayout>
|
# include <QGraphicsBlurEffect>
|
||||||
# include <QHeaderView>
|
# include <QGroupBox>
|
||||||
# include <QIcon>
|
# include <QHBoxLayout>
|
||||||
# include <QImageReader>
|
# include <QHeaderView>
|
||||||
# include <QJsonArray>
|
# include <QIcon>
|
||||||
# include <QJsonDocument>
|
# include <QImageReader>
|
||||||
# include <QJsonObject>
|
# include <QJsonArray>
|
||||||
# include <QJsonValue>
|
# include <QJsonDocument>
|
||||||
# include <QKeyEvent>
|
# include <QJsonObject>
|
||||||
# include <QLabel>
|
# include <QJsonValue>
|
||||||
# include <QLayout>
|
# include <QKeyEvent>
|
||||||
# include <QLibrary>
|
# include <QLabel>
|
||||||
# include <QLineEdit>
|
# include <QLayout>
|
||||||
# include <QList>
|
# include <QLibrary>
|
||||||
# include <QListView>
|
# include <QLineEdit>
|
||||||
# include <QListWidget>
|
# include <QList>
|
||||||
# include <QMap>
|
# include <QListView>
|
||||||
# include <QMediaPlayer>
|
# include <QListWidget>
|
||||||
# include <QMenu>
|
# include <QMap>
|
||||||
# include <QMessageBox>
|
# include <QMediaPlayer>
|
||||||
# include <QMimeData>
|
# include <QMenu>
|
||||||
# include <QMouseEvent>
|
# include <QMessageBox>
|
||||||
# include <QMutex>
|
# include <QMimeData>
|
||||||
# include <QMutexLocker>
|
# include <QMouseEvent>
|
||||||
# include <QNetworkAccessManager>
|
# include <QMutex>
|
||||||
# include <QNetworkReply>
|
# include <QMutexLocker>
|
||||||
# include <QNetworkRequest>
|
# include <QNetworkAccessManager>
|
||||||
# include <QObject>
|
# include <QNetworkReply>
|
||||||
# include <QPaintEvent>
|
# include <QNetworkRequest>
|
||||||
# include <QPainter>
|
# include <QObject>
|
||||||
# include <QPainterPath>
|
# include <QPaintEvent>
|
||||||
# include <QPalette>
|
# include <QPainter>
|
||||||
# include <QPixmap>
|
# include <QPainterPath>
|
||||||
# include <QPoint>
|
# include <QPalette>
|
||||||
# include <QProcess>
|
# include <QPixmap>
|
||||||
# include <QPropertyAnimation>
|
# include <QPoint>
|
||||||
# include <QPushButton>
|
# include <QProcess>
|
||||||
# include <QRadialGradient>
|
# include <QPropertyAnimation>
|
||||||
# include <QRect>
|
# include <QPushButton>
|
||||||
# include <QRegularExpression>
|
# include <QRadialGradient>
|
||||||
# include <QRunnable>
|
# include <QRect>
|
||||||
# include <QScroller>
|
# include <QRegularExpression>
|
||||||
# include <QShortcut>
|
# include <QRunnable>
|
||||||
# include <QSizePolicy>
|
# include <QScroller>
|
||||||
# include <QSlider>
|
# include <QShortcut>
|
||||||
# include <QStackedLayout>
|
# include <QSizePolicy>
|
||||||
# include <QStandardPaths>
|
# include <QSlider>
|
||||||
# include <QString>
|
# include <QStackedLayout>
|
||||||
# include <QStyle>
|
# include <QStandardPaths>
|
||||||
# include <QStyleOption>
|
# include <QString>
|
||||||
# include <QTabWidget>
|
# include <QStyle>
|
||||||
# include <QTextEdit>
|
# include <QStyleOption>
|
||||||
# include <QThread>
|
# include <QTabWidget>
|
||||||
# include <QThreadPool>
|
# include <QTextEdit>
|
||||||
# include <QTime>
|
# include <QThread>
|
||||||
# include <QTimer>
|
# include <QThreadPool>
|
||||||
# include <QUrl>
|
# include <QTime>
|
||||||
# include <QUuid>
|
# include <QTimer>
|
||||||
# include <QVBoxLayout>
|
# include <QUrl>
|
||||||
# include <QVariant>
|
# include <QUuid>
|
||||||
# include <QVector>
|
# include <QVBoxLayout>
|
||||||
# include <QWheelEvent>
|
# include <QVariant>
|
||||||
# include <QWidget>
|
# include <QVector>
|
||||||
# include <QtCore/QVariant>
|
# include <QWheelEvent>
|
||||||
# include <QtGlobal>
|
# include <QWidget>
|
||||||
# include <QtWidgets/QAction>
|
# include <QtCore/QVariant>
|
||||||
# include <QtWidgets/QApplication>
|
# include <QtGlobal>
|
||||||
# include <QtWidgets/QButtonGroup>
|
# include <QtWidgets/QAction>
|
||||||
# include <QtWidgets/QDialog>
|
# include <QtWidgets/QApplication>
|
||||||
# include <QtWidgets/QDialogButtonBox>
|
# include <QtWidgets/QButtonGroup>
|
||||||
# include <QtWidgets/QFormLayout>
|
# include <QtWidgets/QDialog>
|
||||||
# include <QtWidgets/QHBoxLayout>
|
# include <QtWidgets/QDialogButtonBox>
|
||||||
# include <QtWidgets/QHeaderView>
|
# include <QtWidgets/QFormLayout>
|
||||||
# include <QtWidgets/QLabel>
|
# include <QtWidgets/QHBoxLayout>
|
||||||
# include <QtWidgets/QLineEdit>
|
# include <QtWidgets/QHeaderView>
|
||||||
# include <QtWidgets/QPushButton>
|
# include <QtWidgets/QLabel>
|
||||||
# include <QtWidgets/QTabWidget>
|
# include <QtWidgets/QLineEdit>
|
||||||
# include <QtWidgets/QVBoxLayout>
|
# include <QtWidgets/QPushButton>
|
||||||
# include <algorithm>
|
# include <QtWidgets/QTabWidget>
|
||||||
# include <boost/current_function.hpp>
|
# include <QtWidgets/QVBoxLayout>
|
||||||
# include <boost/foreach.hpp>
|
# include <algorithm>
|
||||||
# include <boost/noncopyable.hpp>
|
# include <boost/current_function.hpp>
|
||||||
# include <boost/optional.hpp>
|
# include <boost/foreach.hpp>
|
||||||
# include <cassert>
|
# include <boost/noncopyable.hpp>
|
||||||
# include <chrono>
|
# include <boost/optional.hpp>
|
||||||
# include <cinttypes>
|
# include <cassert>
|
||||||
# include <climits>
|
# include <chrono>
|
||||||
# include <cmath>
|
# include <cinttypes>
|
||||||
# include <cstdint>
|
# include <climits>
|
||||||
# include <ctime>
|
# include <cmath>
|
||||||
# include <functional>
|
# include <cstdint>
|
||||||
# include <future>
|
# include <ctime>
|
||||||
# include <list>
|
# include <functional>
|
||||||
# include <map>
|
# include <future>
|
||||||
# include <memory>
|
# include <list>
|
||||||
# include <mutex>
|
# include <map>
|
||||||
# include <pajlada/serialize.hpp>
|
# include <memory>
|
||||||
# include <pajlada/settings/setting.hpp>
|
# include <mutex>
|
||||||
# include <pajlada/settings/settinglistener.hpp>
|
# include <pajlada/serialize.hpp>
|
||||||
# include <pajlada/signals/connection.hpp>
|
# include <pajlada/settings/setting.hpp>
|
||||||
# include <pajlada/signals/signal.hpp>
|
# include <pajlada/settings/settinglistener.hpp>
|
||||||
# include <random>
|
# include <pajlada/signals/connection.hpp>
|
||||||
# include <set>
|
# include <pajlada/signals/signal.hpp>
|
||||||
# include <string>
|
# include <random>
|
||||||
# include <thread>
|
# include <set>
|
||||||
# include <tuple>
|
# include <string>
|
||||||
# include <type_traits>
|
# include <thread>
|
||||||
# include <unordered_map>
|
# include <tuple>
|
||||||
# include <unordered_set>
|
# include <type_traits>
|
||||||
# include <vector>
|
# include <unordered_map>
|
||||||
|
# include <unordered_set>
|
||||||
# ifndef UNUSED
|
# include <vector>
|
||||||
# define UNUSED(x) (void)(x)
|
|
||||||
# endif
|
# ifndef UNUSED
|
||||||
|
# define UNUSED(x) (void)(x)
|
||||||
# ifndef ATTR_UNUSED
|
# endif
|
||||||
# ifdef Q_OS_WIN
|
|
||||||
# define ATTR_UNUSED
|
# ifndef ATTR_UNUSED
|
||||||
# else
|
# ifdef Q_OS_WIN
|
||||||
# define ATTR_UNUSED __attribute__((unused))
|
# define ATTR_UNUSED
|
||||||
# endif
|
# else
|
||||||
# endif
|
# define ATTR_UNUSED __attribute__((unused))
|
||||||
|
# endif
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
+47
-47
@@ -1,47 +1,47 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Atomic : boost::noncopyable
|
class Atomic : boost::noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Atomic()
|
Atomic()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Atomic(T &&val)
|
Atomic(T &&val)
|
||||||
: value_(val)
|
: value_(val)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
T get() const
|
T get() const
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(this->mutex_);
|
std::lock_guard<std::mutex> guard(this->mutex_);
|
||||||
|
|
||||||
return this->value_;
|
return this->value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(const T &val)
|
void set(const T &val)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(this->mutex_);
|
std::lock_guard<std::mutex> guard(this->mutex_);
|
||||||
|
|
||||||
this->value_ = val;
|
this->value_ = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(T &&val)
|
void set(T &&val)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(this->mutex_);
|
std::lock_guard<std::mutex> guard(this->mutex_);
|
||||||
|
|
||||||
this->value_ = std::move(val);
|
this->value_ = std::move(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable std::mutex mutex_;
|
mutable std::mutex mutex_;
|
||||||
T value_;
|
T value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
+49
-49
@@ -1,49 +1,49 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/Aliases.hpp"
|
#include "common/Aliases.hpp"
|
||||||
#include "common/Outcome.hpp"
|
#include "common/Outcome.hpp"
|
||||||
#include "common/ProviderId.hpp"
|
#include "common/ProviderId.hpp"
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <boost/preprocessor.hpp>
|
#include <boost/preprocessor.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
enum class HighlightState {
|
enum class HighlightState {
|
||||||
None,
|
None,
|
||||||
Highlighted,
|
Highlighted,
|
||||||
NewMessage,
|
NewMessage,
|
||||||
};
|
};
|
||||||
|
|
||||||
inline QString qS(const std::string &string)
|
inline QString qS(const std::string &string)
|
||||||
{
|
{
|
||||||
return QString::fromStdString(string);
|
return QString::fromStdString(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Qt::KeyboardModifiers showSplitOverlayModifiers =
|
const Qt::KeyboardModifiers showSplitOverlayModifiers =
|
||||||
Qt::ControlModifier | Qt::AltModifier;
|
Qt::ControlModifier | Qt::AltModifier;
|
||||||
const Qt::KeyboardModifiers showAddSplitRegions =
|
const Qt::KeyboardModifiers showAddSplitRegions =
|
||||||
Qt::ControlModifier | Qt::AltModifier;
|
Qt::ControlModifier | Qt::AltModifier;
|
||||||
const Qt::KeyboardModifiers showResizeHandlesModifiers = Qt::ControlModifier;
|
const Qt::KeyboardModifiers showResizeHandlesModifiers = Qt::ControlModifier;
|
||||||
|
|
||||||
static const char *ANONYMOUS_USERNAME_LABEL ATTR_UNUSED = " - anonymous - ";
|
static const char *ANONYMOUS_USERNAME_LABEL ATTR_UNUSED = " - anonymous - ";
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::weak_ptr<T> weakOf(T *element)
|
std::weak_ptr<T> weakOf(T *element)
|
||||||
{
|
{
|
||||||
return element->shared_from_this();
|
return element->shared_from_this();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Message;
|
struct Message;
|
||||||
using MessagePtr = std::shared_ptr<const Message>;
|
using MessagePtr = std::shared_ptr<const Message>;
|
||||||
|
|
||||||
enum class CopyMode {
|
enum class CopyMode {
|
||||||
Everything,
|
Everything,
|
||||||
OnlyTextAndEmotes,
|
OnlyTextAndEmotes,
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
+195
-195
@@ -1,195 +1,195 @@
|
|||||||
#include "common/CompletionModel.hpp"
|
#include "common/CompletionModel.hpp"
|
||||||
|
|
||||||
#include "Application.hpp"
|
#include "Application.hpp"
|
||||||
#include "common/Common.hpp"
|
#include "common/Common.hpp"
|
||||||
#include "common/UsernameSet.hpp"
|
#include "common/UsernameSet.hpp"
|
||||||
#include "controllers/accounts/AccountController.hpp"
|
#include "controllers/accounts/AccountController.hpp"
|
||||||
#include "controllers/commands/CommandController.hpp"
|
#include "controllers/commands/CommandController.hpp"
|
||||||
#include "debug/Benchmark.hpp"
|
#include "debug/Benchmark.hpp"
|
||||||
#include "debug/Log.hpp"
|
#include "debug/Log.hpp"
|
||||||
#include "providers/twitch/TwitchChannel.hpp"
|
#include "providers/twitch/TwitchChannel.hpp"
|
||||||
#include "providers/twitch/TwitchIrcServer.hpp"
|
#include "providers/twitch/TwitchIrcServer.hpp"
|
||||||
#include "singletons/Emotes.hpp"
|
#include "singletons/Emotes.hpp"
|
||||||
#include "singletons/Settings.hpp"
|
#include "singletons/Settings.hpp"
|
||||||
|
|
||||||
#include <QtAlgorithms>
|
#include <QtAlgorithms>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
//
|
//
|
||||||
// TaggedString
|
// TaggedString
|
||||||
//
|
//
|
||||||
|
|
||||||
CompletionModel::TaggedString::TaggedString(const QString &_string, Type _type)
|
CompletionModel::TaggedString::TaggedString(const QString &_string, Type _type)
|
||||||
: string(_string)
|
: string(_string)
|
||||||
, type(_type)
|
, type(_type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CompletionModel::TaggedString::isEmote() const
|
bool CompletionModel::TaggedString::isEmote() const
|
||||||
{
|
{
|
||||||
return this->type > Type::EmoteStart && this->type < Type::EmoteEnd;
|
return this->type > Type::EmoteStart && this->type < Type::EmoteEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CompletionModel::TaggedString::operator<(const TaggedString &that) const
|
bool CompletionModel::TaggedString::operator<(const TaggedString &that) const
|
||||||
{
|
{
|
||||||
if (this->isEmote() != that.isEmote())
|
if (this->isEmote() != that.isEmote())
|
||||||
{
|
{
|
||||||
return this->isEmote();
|
return this->isEmote();
|
||||||
}
|
}
|
||||||
|
|
||||||
// try comparing insensitively, if they are the same then senstively
|
// try comparing insensitively, if they are the same then senstively
|
||||||
// (fixes order of LuL and LUL)
|
// (fixes order of LuL and LUL)
|
||||||
int k = QString::compare(this->string, that.string, Qt::CaseInsensitive);
|
int k = QString::compare(this->string, that.string, Qt::CaseInsensitive);
|
||||||
if (k == 0)
|
if (k == 0)
|
||||||
return this->string > that.string;
|
return this->string > that.string;
|
||||||
|
|
||||||
return k < 0;
|
return k < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// CompletionModel
|
// CompletionModel
|
||||||
//
|
//
|
||||||
CompletionModel::CompletionModel(Channel &channel)
|
CompletionModel::CompletionModel(Channel &channel)
|
||||||
: channel_(channel)
|
: channel_(channel)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int CompletionModel::columnCount(const QModelIndex &) const
|
int CompletionModel::columnCount(const QModelIndex &) const
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant CompletionModel::data(const QModelIndex &index, int) const
|
QVariant CompletionModel::data(const QModelIndex &index, int) const
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(this->itemsMutex_);
|
std::lock_guard<std::mutex> lock(this->itemsMutex_);
|
||||||
|
|
||||||
auto it = this->items_.begin();
|
auto it = this->items_.begin();
|
||||||
std::advance(it, index.row());
|
std::advance(it, index.row());
|
||||||
return QVariant(it->string);
|
return QVariant(it->string);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CompletionModel::rowCount(const QModelIndex &) const
|
int CompletionModel::rowCount(const QModelIndex &) const
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(this->itemsMutex_);
|
std::lock_guard<std::mutex> lock(this->itemsMutex_);
|
||||||
|
|
||||||
return this->items_.size();
|
return this->items_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompletionModel::refresh(const QString &prefix, bool isFirstWord)
|
void CompletionModel::refresh(const QString &prefix, bool isFirstWord)
|
||||||
{
|
{
|
||||||
std::function<void(const QString &, TaggedString::Type)> addString;
|
std::function<void(const QString &, TaggedString::Type)> addString;
|
||||||
if (getSettings()->prefixOnlyEmoteCompletion)
|
if (getSettings()->prefixOnlyEmoteCompletion)
|
||||||
{
|
{
|
||||||
addString = [&](const QString &str, TaggedString::Type type) {
|
addString = [&](const QString &str, TaggedString::Type type) {
|
||||||
if (str.startsWith(prefix, Qt::CaseInsensitive))
|
if (str.startsWith(prefix, Qt::CaseInsensitive))
|
||||||
this->items_.emplace(str + " ", type);
|
this->items_.emplace(str + " ", type);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
addString = [&](const QString &str, TaggedString::Type type) {
|
addString = [&](const QString &str, TaggedString::Type type) {
|
||||||
if (str.contains(prefix, Qt::CaseInsensitive))
|
if (str.contains(prefix, Qt::CaseInsensitive))
|
||||||
this->items_.emplace(str + " ", type);
|
this->items_.emplace(str + " ", type);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> guard(this->itemsMutex_);
|
std::lock_guard<std::mutex> guard(this->itemsMutex_);
|
||||||
this->items_.clear();
|
this->items_.clear();
|
||||||
|
|
||||||
if (prefix.length() < 2)
|
if (prefix.length() < 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (auto channel = dynamic_cast<TwitchChannel *>(&this->channel_))
|
if (auto channel = dynamic_cast<TwitchChannel *>(&this->channel_))
|
||||||
{
|
{
|
||||||
// account emotes
|
// account emotes
|
||||||
if (auto account = getApp()->accounts->twitch.getCurrent())
|
if (auto account = getApp()->accounts->twitch.getCurrent())
|
||||||
{
|
{
|
||||||
for (const auto &emote : account->accessEmotes()->allEmoteNames)
|
for (const auto &emote : account->accessEmotes()->allEmoteNames)
|
||||||
{
|
{
|
||||||
// XXX: No way to discern between a twitch global emote and sub
|
// XXX: No way to discern between a twitch global emote and sub
|
||||||
// emote right now
|
// emote right now
|
||||||
addString(emote.string, TaggedString::Type::TwitchGlobalEmote);
|
addString(emote.string, TaggedString::Type::TwitchGlobalEmote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Usernames
|
// Usernames
|
||||||
if (prefix.length() >= UsernameSet::PrefixLength)
|
if (prefix.length() >= UsernameSet::PrefixLength)
|
||||||
{
|
{
|
||||||
auto usernames = channel->accessChatters();
|
auto usernames = channel->accessChatters();
|
||||||
|
|
||||||
QString usernamePrefix = prefix;
|
QString usernamePrefix = prefix;
|
||||||
QString usernamePostfix =
|
QString usernamePostfix =
|
||||||
isFirstWord && getSettings()->mentionUsersWithComma ? ","
|
isFirstWord && getSettings()->mentionUsersWithComma ? ","
|
||||||
: QString();
|
: QString();
|
||||||
|
|
||||||
if (usernamePrefix.startsWith("@"))
|
if (usernamePrefix.startsWith("@"))
|
||||||
{
|
{
|
||||||
usernamePrefix.remove(0, 1);
|
usernamePrefix.remove(0, 1);
|
||||||
for (const auto &name :
|
for (const auto &name :
|
||||||
usernames->subrange(Prefix(usernamePrefix)))
|
usernames->subrange(Prefix(usernamePrefix)))
|
||||||
{
|
{
|
||||||
addString("@" + name + usernamePostfix,
|
addString("@" + name + usernamePostfix,
|
||||||
TaggedString::Type::Username);
|
TaggedString::Type::Username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (const auto &name :
|
for (const auto &name :
|
||||||
usernames->subrange(Prefix(usernamePrefix)))
|
usernames->subrange(Prefix(usernamePrefix)))
|
||||||
{
|
{
|
||||||
addString(name + usernamePostfix,
|
addString(name + usernamePostfix,
|
||||||
TaggedString::Type::Username);
|
TaggedString::Type::Username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bttv Global
|
// Bttv Global
|
||||||
for (auto &emote : *channel->globalBttv().emotes())
|
for (auto &emote : *channel->globalBttv().emotes())
|
||||||
{
|
{
|
||||||
addString(emote.first.string, TaggedString::Type::BTTVChannelEmote);
|
addString(emote.first.string, TaggedString::Type::BTTVChannelEmote);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ffz Global
|
// Ffz Global
|
||||||
for (auto &emote : *channel->globalFfz().emotes())
|
for (auto &emote : *channel->globalFfz().emotes())
|
||||||
{
|
{
|
||||||
addString(emote.first.string, TaggedString::Type::FFZChannelEmote);
|
addString(emote.first.string, TaggedString::Type::FFZChannelEmote);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bttv Channel
|
// Bttv Channel
|
||||||
for (auto &emote : *channel->bttvEmotes())
|
for (auto &emote : *channel->bttvEmotes())
|
||||||
{
|
{
|
||||||
addString(emote.first.string, TaggedString::Type::BTTVGlobalEmote);
|
addString(emote.first.string, TaggedString::Type::BTTVGlobalEmote);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ffz Channel
|
// Ffz Channel
|
||||||
for (auto &emote : *channel->ffzEmotes())
|
for (auto &emote : *channel->ffzEmotes())
|
||||||
{
|
{
|
||||||
addString(emote.first.string, TaggedString::Type::BTTVGlobalEmote);
|
addString(emote.first.string, TaggedString::Type::BTTVGlobalEmote);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emojis
|
// Emojis
|
||||||
if (prefix.startsWith(":"))
|
if (prefix.startsWith(":"))
|
||||||
{
|
{
|
||||||
const auto &emojiShortCodes = getApp()->emotes->emojis.shortCodes;
|
const auto &emojiShortCodes = getApp()->emotes->emojis.shortCodes;
|
||||||
for (auto &m : emojiShortCodes)
|
for (auto &m : emojiShortCodes)
|
||||||
{
|
{
|
||||||
addString(":" + m + ":", TaggedString::Type::Emoji);
|
addString(":" + m + ":", TaggedString::Type::Emoji);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
for (auto &command : getApp()->commands->items_)
|
for (auto &command : getApp()->commands->items_)
|
||||||
{
|
{
|
||||||
addString(command.name, TaggedString::Command);
|
addString(command.name, TaggedString::Command);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &command : getApp()->commands->getDefaultTwitchCommandList())
|
for (auto &command : getApp()->commands->getDefaultTwitchCommandList())
|
||||||
{
|
{
|
||||||
addString(command, TaggedString::Command);
|
addString(command, TaggedString::Command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,60 +1,60 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class Channel;
|
class Channel;
|
||||||
|
|
||||||
class CompletionModel : public QAbstractListModel
|
class CompletionModel : public QAbstractListModel
|
||||||
{
|
{
|
||||||
struct TaggedString {
|
struct TaggedString {
|
||||||
enum Type {
|
enum Type {
|
||||||
Username,
|
Username,
|
||||||
|
|
||||||
// emotes
|
// emotes
|
||||||
EmoteStart,
|
EmoteStart,
|
||||||
FFZGlobalEmote,
|
FFZGlobalEmote,
|
||||||
FFZChannelEmote,
|
FFZChannelEmote,
|
||||||
BTTVGlobalEmote,
|
BTTVGlobalEmote,
|
||||||
BTTVChannelEmote,
|
BTTVChannelEmote,
|
||||||
TwitchGlobalEmote,
|
TwitchGlobalEmote,
|
||||||
TwitchSubscriberEmote,
|
TwitchSubscriberEmote,
|
||||||
Emoji,
|
Emoji,
|
||||||
EmoteEnd,
|
EmoteEnd,
|
||||||
// end emotes
|
// end emotes
|
||||||
|
|
||||||
Command,
|
Command,
|
||||||
};
|
};
|
||||||
|
|
||||||
TaggedString(const QString &string, Type type);
|
TaggedString(const QString &string, Type type);
|
||||||
|
|
||||||
bool isEmote() const;
|
bool isEmote() const;
|
||||||
bool operator<(const TaggedString &that) const;
|
bool operator<(const TaggedString &that) const;
|
||||||
|
|
||||||
QString string;
|
QString string;
|
||||||
Type type;
|
Type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CompletionModel(Channel &channel);
|
CompletionModel(Channel &channel);
|
||||||
|
|
||||||
virtual int columnCount(const QModelIndex &) const override;
|
virtual int columnCount(const QModelIndex &) const override;
|
||||||
virtual QVariant data(const QModelIndex &index, int) const override;
|
virtual QVariant data(const QModelIndex &index, int) const override;
|
||||||
virtual int rowCount(const QModelIndex &) const override;
|
virtual int rowCount(const QModelIndex &) const override;
|
||||||
|
|
||||||
void refresh(const QString &prefix, bool isFirstWord = false);
|
void refresh(const QString &prefix, bool isFirstWord = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TaggedString createUser(const QString &str);
|
TaggedString createUser(const QString &str);
|
||||||
|
|
||||||
std::set<TaggedString> items_;
|
std::set<TaggedString> items_;
|
||||||
mutable std::mutex itemsMutex_;
|
mutable std::mutex itemsMutex_;
|
||||||
Channel &channel_;
|
Channel &channel_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#include "Modes.hpp"
|
||||||
|
|
||||||
|
#include "util/CombinePath.hpp"
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
Modes::Modes()
|
||||||
|
{
|
||||||
|
QFile file(combinePath(QCoreApplication::applicationDirPath(), "modes"));
|
||||||
|
file.open(QIODevice::ReadOnly);
|
||||||
|
|
||||||
|
while (!file.atEnd())
|
||||||
|
{
|
||||||
|
auto line = QString(file.readLine()).trimmed();
|
||||||
|
|
||||||
|
// we need to know if it is a nightly build to disable updates on windows
|
||||||
|
if (line == "nightly")
|
||||||
|
{
|
||||||
|
this->isNightly = true;
|
||||||
|
}
|
||||||
|
else if (line == "portable")
|
||||||
|
{
|
||||||
|
this->isPortable = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Modes &Modes::getInstance()
|
||||||
|
{
|
||||||
|
static Modes instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
class Modes
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Modes();
|
||||||
|
|
||||||
|
static const Modes &getInstance();
|
||||||
|
|
||||||
|
bool isNightly{};
|
||||||
|
bool isPortable{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -32,6 +32,10 @@ NetworkData::~NetworkData()
|
|||||||
|
|
||||||
QString NetworkData::getHash()
|
QString NetworkData::getHash()
|
||||||
{
|
{
|
||||||
|
static std::mutex mu;
|
||||||
|
|
||||||
|
std::lock_guard lock(mu);
|
||||||
|
|
||||||
if (this->hash_.isEmpty())
|
if (this->hash_.isEmpty())
|
||||||
{
|
{
|
||||||
QByteArray bytes;
|
QByteArray bytes;
|
||||||
@@ -242,7 +246,6 @@ void load(const std::shared_ptr<NetworkData> &data)
|
|||||||
if (data->cache_)
|
if (data->cache_)
|
||||||
{
|
{
|
||||||
QtConcurrent::run(loadCached, data);
|
QtConcurrent::run(loadCached, data);
|
||||||
loadCached(data);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
+73
-73
@@ -1,73 +1,73 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class NullablePtr
|
class NullablePtr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NullablePtr()
|
NullablePtr()
|
||||||
: element_(nullptr)
|
: element_(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NullablePtr(T *element)
|
NullablePtr(T *element)
|
||||||
: element_(element)
|
: element_(element)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
T *operator->() const
|
T *operator->() const
|
||||||
{
|
{
|
||||||
assert(this->hasElement());
|
assert(this->hasElement());
|
||||||
|
|
||||||
return element_;
|
return element_;
|
||||||
}
|
}
|
||||||
|
|
||||||
typename std::add_lvalue_reference<T>::type operator*() const
|
typename std::add_lvalue_reference<T>::type operator*() const
|
||||||
{
|
{
|
||||||
assert(this->hasElement());
|
assert(this->hasElement());
|
||||||
|
|
||||||
return *element_;
|
return *element_;
|
||||||
}
|
}
|
||||||
|
|
||||||
T *get() const
|
T *get() const
|
||||||
{
|
{
|
||||||
assert(this->hasElement());
|
assert(this->hasElement());
|
||||||
|
|
||||||
return this->element_;
|
return this->element_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNull() const
|
bool isNull() const
|
||||||
{
|
{
|
||||||
return this->element_ == nullptr;
|
return this->element_ == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasElement() const
|
bool hasElement() const
|
||||||
{
|
{
|
||||||
return this->element_ != nullptr;
|
return this->element_ != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator bool() const
|
operator bool() const
|
||||||
{
|
{
|
||||||
return this->hasElement();
|
return this->hasElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!() const
|
bool operator!() const
|
||||||
{
|
{
|
||||||
return !this->hasElement();
|
return !this->hasElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename X = T,
|
template <typename X = T,
|
||||||
typename = std::enable_if_t<!std::is_const<X>::value>>
|
typename = std::enable_if_t<!std::is_const<X>::value>>
|
||||||
operator NullablePtr<const T>() const
|
operator NullablePtr<const T>() const
|
||||||
{
|
{
|
||||||
return NullablePtr<const T>(this->element_);
|
return NullablePtr<const T>(this->element_);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T *element_;
|
T *element_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
enum class ProviderId { Twitch, Irc };
|
enum class ProviderId { Twitch, Irc };
|
||||||
//
|
//
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
+247
-247
@@ -1,247 +1,247 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <pajlada/signals/signal.hpp>
|
#include <pajlada/signals/signal.hpp>
|
||||||
#include <shared_mutex>
|
#include <shared_mutex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "debug/AssertInGuiThread.hpp"
|
#include "debug/AssertInGuiThread.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
template <typename TVectorItem>
|
template <typename TVectorItem>
|
||||||
struct SignalVectorItemArgs {
|
struct SignalVectorItemArgs {
|
||||||
const TVectorItem &item;
|
const TVectorItem &item;
|
||||||
int index;
|
int index;
|
||||||
void *caller;
|
void *caller;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TVectorItem>
|
template <typename TVectorItem>
|
||||||
class ReadOnlySignalVector : boost::noncopyable
|
class ReadOnlySignalVector : boost::noncopyable
|
||||||
{
|
{
|
||||||
using VecIt = typename std::vector<TVectorItem>::iterator;
|
using VecIt = typename std::vector<TVectorItem>::iterator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Iterator
|
struct Iterator
|
||||||
: public std::iterator<std::input_iterator_tag, TVectorItem> {
|
: public std::iterator<std::input_iterator_tag, TVectorItem> {
|
||||||
Iterator(VecIt &&it, std::shared_mutex &mutex)
|
Iterator(VecIt &&it, std::shared_mutex &mutex)
|
||||||
: it_(std::move(it))
|
: it_(std::move(it))
|
||||||
, lock_(mutex)
|
, lock_(mutex)
|
||||||
, mutex_(mutex)
|
, mutex_(mutex)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator(const Iterator &other)
|
Iterator(const Iterator &other)
|
||||||
: it_(other.it_)
|
: it_(other.it_)
|
||||||
, lock_(other.mutex_)
|
, lock_(other.mutex_)
|
||||||
, mutex_(other.mutex_)
|
, mutex_(other.mutex_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator &operator=(const Iterator &other)
|
Iterator &operator=(const Iterator &other)
|
||||||
{
|
{
|
||||||
this->lock_ = std::shared_lock(other.mutex_.get());
|
this->lock_ = std::shared_lock(other.mutex_.get());
|
||||||
this->mutex_ = other.mutex_;
|
this->mutex_ = other.mutex_;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TVectorItem &operator*()
|
TVectorItem &operator*()
|
||||||
{
|
{
|
||||||
return it_.operator*();
|
return it_.operator*();
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator &operator++()
|
Iterator &operator++()
|
||||||
{
|
{
|
||||||
++this->it_;
|
++this->it_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const Iterator &other)
|
bool operator==(const Iterator &other)
|
||||||
{
|
{
|
||||||
return this->it_ == other.it_;
|
return this->it_ == other.it_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const Iterator &other)
|
bool operator!=(const Iterator &other)
|
||||||
{
|
{
|
||||||
return this->it_ != other.it_;
|
return this->it_ != other.it_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator-(const Iterator &other)
|
auto operator-(const Iterator &other)
|
||||||
{
|
{
|
||||||
return this->it_ - other.it_;
|
return this->it_ - other.it_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VecIt it_;
|
VecIt it_;
|
||||||
std::shared_lock<std::shared_mutex> lock_;
|
std::shared_lock<std::shared_mutex> lock_;
|
||||||
std::reference_wrapper<std::shared_mutex> mutex_;
|
std::reference_wrapper<std::shared_mutex> mutex_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ReadOnlySignalVector()
|
ReadOnlySignalVector()
|
||||||
{
|
{
|
||||||
QObject::connect(&this->itemsChangedTimer_, &QTimer::timeout,
|
QObject::connect(&this->itemsChangedTimer_, &QTimer::timeout,
|
||||||
[this] { this->delayedItemsChanged.invoke(); });
|
[this] { this->delayedItemsChanged.invoke(); });
|
||||||
this->itemsChangedTimer_.setInterval(100);
|
this->itemsChangedTimer_.setInterval(100);
|
||||||
this->itemsChangedTimer_.setSingleShot(true);
|
this->itemsChangedTimer_.setSingleShot(true);
|
||||||
}
|
}
|
||||||
virtual ~ReadOnlySignalVector() = default;
|
virtual ~ReadOnlySignalVector() = default;
|
||||||
|
|
||||||
pajlada::Signals::Signal<SignalVectorItemArgs<TVectorItem>> itemInserted;
|
pajlada::Signals::Signal<SignalVectorItemArgs<TVectorItem>> itemInserted;
|
||||||
pajlada::Signals::Signal<SignalVectorItemArgs<TVectorItem>> itemRemoved;
|
pajlada::Signals::Signal<SignalVectorItemArgs<TVectorItem>> itemRemoved;
|
||||||
pajlada::Signals::NoArgSignal delayedItemsChanged;
|
pajlada::Signals::NoArgSignal delayedItemsChanged;
|
||||||
|
|
||||||
Iterator begin() const
|
Iterator begin() const
|
||||||
{
|
{
|
||||||
return Iterator(
|
return Iterator(
|
||||||
const_cast<std::vector<TVectorItem> &>(this->vector_).begin(),
|
const_cast<std::vector<TVectorItem> &>(this->vector_).begin(),
|
||||||
this->mutex_);
|
this->mutex_);
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator end() const
|
Iterator end() const
|
||||||
{
|
{
|
||||||
return Iterator(
|
return Iterator(
|
||||||
const_cast<std::vector<TVectorItem> &>(this->vector_).end(),
|
const_cast<std::vector<TVectorItem> &>(this->vector_).end(),
|
||||||
this->mutex_);
|
this->mutex_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty() const
|
bool empty() const
|
||||||
{
|
{
|
||||||
std::shared_lock lock(this->mutex_);
|
std::shared_lock lock(this->mutex_);
|
||||||
|
|
||||||
return this->vector_.empty();
|
return this->vector_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<TVectorItem> &getVector() const
|
const std::vector<TVectorItem> &getVector() const
|
||||||
{
|
{
|
||||||
assertInGuiThread();
|
assertInGuiThread();
|
||||||
|
|
||||||
return this->vector_;
|
return this->vector_;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<TVectorItem> cloneVector() const
|
std::vector<TVectorItem> cloneVector() const
|
||||||
{
|
{
|
||||||
std::shared_lock lock(this->mutex_);
|
std::shared_lock lock(this->mutex_);
|
||||||
|
|
||||||
return this->vector_;
|
return this->vector_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void invokeDelayedItemsChanged()
|
void invokeDelayedItemsChanged()
|
||||||
{
|
{
|
||||||
assertInGuiThread();
|
assertInGuiThread();
|
||||||
|
|
||||||
if (!this->itemsChangedTimer_.isActive())
|
if (!this->itemsChangedTimer_.isActive())
|
||||||
{
|
{
|
||||||
this->itemsChangedTimer_.start();
|
this->itemsChangedTimer_.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool isSorted() const = 0;
|
virtual bool isSorted() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<TVectorItem> vector_;
|
std::vector<TVectorItem> vector_;
|
||||||
QTimer itemsChangedTimer_;
|
QTimer itemsChangedTimer_;
|
||||||
mutable std::shared_mutex mutex_;
|
mutable std::shared_mutex mutex_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TVectorItem>
|
template <typename TVectorItem>
|
||||||
class BaseSignalVector : public ReadOnlySignalVector<TVectorItem>
|
class BaseSignalVector : public ReadOnlySignalVector<TVectorItem>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// returns the actual index of the inserted item
|
// returns the actual index of the inserted item
|
||||||
virtual int insertItem(const TVectorItem &item, int proposedIndex = -1,
|
virtual int insertItem(const TVectorItem &item, int proposedIndex = -1,
|
||||||
void *caller = nullptr) = 0;
|
void *caller = nullptr) = 0;
|
||||||
|
|
||||||
void removeItem(int index, void *caller = nullptr)
|
void removeItem(int index, void *caller = nullptr)
|
||||||
{
|
{
|
||||||
assertInGuiThread();
|
assertInGuiThread();
|
||||||
std::unique_lock lock(this->mutex_);
|
std::unique_lock lock(this->mutex_);
|
||||||
|
|
||||||
assert(index >= 0 && index < int(this->vector_.size()));
|
assert(index >= 0 && index < int(this->vector_.size()));
|
||||||
|
|
||||||
TVectorItem item = this->vector_[index];
|
TVectorItem item = this->vector_[index];
|
||||||
|
|
||||||
this->vector_.erase(this->vector_.begin() + index);
|
this->vector_.erase(this->vector_.begin() + index);
|
||||||
lock.unlock(); // manual unlock
|
lock.unlock(); // manual unlock
|
||||||
|
|
||||||
SignalVectorItemArgs<TVectorItem> args{item, index, caller};
|
SignalVectorItemArgs<TVectorItem> args{item, index, caller};
|
||||||
this->itemRemoved.invoke(args);
|
this->itemRemoved.invoke(args);
|
||||||
|
|
||||||
this->invokeDelayedItemsChanged();
|
this->invokeDelayedItemsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
int appendItem(const TVectorItem &item, void *caller = nullptr)
|
int appendItem(const TVectorItem &item, void *caller = nullptr)
|
||||||
{
|
{
|
||||||
return this->insertItem(item, -1, caller);
|
return this->insertItem(item, -1, caller);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TVectorItem>
|
template <typename TVectorItem>
|
||||||
class UnsortedSignalVector : public BaseSignalVector<TVectorItem>
|
class UnsortedSignalVector : public BaseSignalVector<TVectorItem>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual int insertItem(const TVectorItem &item, int index = -1,
|
virtual int insertItem(const TVectorItem &item, int index = -1,
|
||||||
void *caller = nullptr) override
|
void *caller = nullptr) override
|
||||||
{
|
{
|
||||||
assertInGuiThread();
|
assertInGuiThread();
|
||||||
|
|
||||||
{
|
{
|
||||||
std::unique_lock lock(this->mutex_);
|
std::unique_lock lock(this->mutex_);
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
{
|
{
|
||||||
index = this->vector_.size();
|
index = this->vector_.size();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(index >= 0 && index <= this->vector_.size());
|
assert(index >= 0 && index <= this->vector_.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
this->vector_.insert(this->vector_.begin() + index, item);
|
this->vector_.insert(this->vector_.begin() + index, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
SignalVectorItemArgs<TVectorItem> args{item, index, caller};
|
SignalVectorItemArgs<TVectorItem> args{item, index, caller};
|
||||||
this->itemInserted.invoke(args);
|
this->itemInserted.invoke(args);
|
||||||
this->invokeDelayedItemsChanged();
|
this->invokeDelayedItemsChanged();
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool isSorted() const override
|
virtual bool isSorted() const override
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TVectorItem, typename Compare>
|
template <typename TVectorItem, typename Compare>
|
||||||
class SortedSignalVector : public BaseSignalVector<TVectorItem>
|
class SortedSignalVector : public BaseSignalVector<TVectorItem>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual int insertItem(const TVectorItem &item, int = -1,
|
virtual int insertItem(const TVectorItem &item, int = -1,
|
||||||
void *caller = nullptr) override
|
void *caller = nullptr) override
|
||||||
{
|
{
|
||||||
assertInGuiThread();
|
assertInGuiThread();
|
||||||
int index = -1;
|
int index = -1;
|
||||||
|
|
||||||
{
|
{
|
||||||
std::unique_lock lock(this->mutex_);
|
std::unique_lock lock(this->mutex_);
|
||||||
|
|
||||||
auto it = std::lower_bound(this->vector_.begin(),
|
auto it = std::lower_bound(this->vector_.begin(),
|
||||||
this->vector_.end(), item, Compare{});
|
this->vector_.end(), item, Compare{});
|
||||||
index = it - this->vector_.begin();
|
index = it - this->vector_.begin();
|
||||||
this->vector_.insert(it, item);
|
this->vector_.insert(it, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
SignalVectorItemArgs<TVectorItem> args{item, index, caller};
|
SignalVectorItemArgs<TVectorItem> args{item, index, caller};
|
||||||
this->itemInserted.invoke(args);
|
this->itemInserted.invoke(args);
|
||||||
this->invokeDelayedItemsChanged();
|
this->invokeDelayedItemsChanged();
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool isSorted() const override
|
virtual bool isSorted() const override
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
+380
-380
@@ -1,380 +1,380 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/SignalVector.hpp"
|
#include "common/SignalVector.hpp"
|
||||||
|
|
||||||
#include <QAbstractTableModel>
|
#include <QAbstractTableModel>
|
||||||
#include <QStandardItem>
|
#include <QStandardItem>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
#include <pajlada/signals/signalholder.hpp>
|
#include <pajlada/signals/signalholder.hpp>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
template <typename TVectorItem>
|
template <typename TVectorItem>
|
||||||
class SignalVectorModel : public QAbstractTableModel,
|
class SignalVectorModel : public QAbstractTableModel,
|
||||||
pajlada::Signals::SignalHolder
|
pajlada::Signals::SignalHolder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SignalVectorModel(int columnCount, QObject *parent = nullptr)
|
SignalVectorModel(int columnCount, QObject *parent = nullptr)
|
||||||
: QAbstractTableModel(parent)
|
: QAbstractTableModel(parent)
|
||||||
, columnCount_(columnCount)
|
, columnCount_(columnCount)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < columnCount; i++)
|
for (int i = 0; i < columnCount; i++)
|
||||||
{
|
{
|
||||||
this->headerData_.emplace_back();
|
this->headerData_.emplace_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(BaseSignalVector<TVectorItem> *vec)
|
void init(BaseSignalVector<TVectorItem> *vec)
|
||||||
{
|
{
|
||||||
this->vector_ = vec;
|
this->vector_ = vec;
|
||||||
|
|
||||||
auto insert = [this](const SignalVectorItemArgs<TVectorItem> &args) {
|
auto insert = [this](const SignalVectorItemArgs<TVectorItem> &args) {
|
||||||
if (args.caller == this)
|
if (args.caller == this)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// get row index
|
// get row index
|
||||||
int index = this->getModelIndexFromVectorIndex(args.index);
|
int index = this->getModelIndexFromVectorIndex(args.index);
|
||||||
assert(index >= 0 && index <= this->rows_.size());
|
assert(index >= 0 && index <= this->rows_.size());
|
||||||
|
|
||||||
// get row items
|
// get row items
|
||||||
std::vector<QStandardItem *> row = this->createRow();
|
std::vector<QStandardItem *> row = this->createRow();
|
||||||
this->getRowFromItem(args.item, row);
|
this->getRowFromItem(args.item, row);
|
||||||
|
|
||||||
// insert row
|
// insert row
|
||||||
index = this->beforeInsert(args.item, row, index);
|
index = this->beforeInsert(args.item, row, index);
|
||||||
|
|
||||||
this->beginInsertRows(QModelIndex(), index, index);
|
this->beginInsertRows(QModelIndex(), index, index);
|
||||||
this->rows_.insert(this->rows_.begin() + index,
|
this->rows_.insert(this->rows_.begin() + index,
|
||||||
Row(row, args.item));
|
Row(row, args.item));
|
||||||
this->endInsertRows();
|
this->endInsertRows();
|
||||||
};
|
};
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (const TVectorItem &item : vec->getVector())
|
for (const TVectorItem &item : vec->getVector())
|
||||||
{
|
{
|
||||||
SignalVectorItemArgs<TVectorItem> args{item, i++, 0};
|
SignalVectorItemArgs<TVectorItem> args{item, i++, 0};
|
||||||
|
|
||||||
insert(args);
|
insert(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->managedConnect(vec->itemInserted, insert);
|
this->managedConnect(vec->itemInserted, insert);
|
||||||
|
|
||||||
this->managedConnect(vec->itemRemoved, [this](auto args) {
|
this->managedConnect(vec->itemRemoved, [this](auto args) {
|
||||||
if (args.caller == this)
|
if (args.caller == this)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int row = this->getModelIndexFromVectorIndex(args.index);
|
int row = this->getModelIndexFromVectorIndex(args.index);
|
||||||
assert(row >= 0 && row <= this->rows_.size());
|
assert(row >= 0 && row <= this->rows_.size());
|
||||||
|
|
||||||
// remove row
|
// remove row
|
||||||
std::vector<QStandardItem *> items =
|
std::vector<QStandardItem *> items =
|
||||||
std::move(this->rows_[row].items);
|
std::move(this->rows_[row].items);
|
||||||
|
|
||||||
this->beginRemoveRows(QModelIndex(), row, row);
|
this->beginRemoveRows(QModelIndex(), row, row);
|
||||||
this->rows_.erase(this->rows_.begin() + row);
|
this->rows_.erase(this->rows_.begin() + row);
|
||||||
this->endRemoveRows();
|
this->endRemoveRows();
|
||||||
|
|
||||||
this->afterRemoved(args.item, items, row);
|
this->afterRemoved(args.item, items, row);
|
||||||
|
|
||||||
for (QStandardItem *item : items)
|
for (QStandardItem *item : items)
|
||||||
{
|
{
|
||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this->afterInit();
|
this->afterInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~SignalVectorModel()
|
virtual ~SignalVectorModel()
|
||||||
{
|
{
|
||||||
for (Row &row : this->rows_)
|
for (Row &row : this->rows_)
|
||||||
{
|
{
|
||||||
for (QStandardItem *item : row.items)
|
for (QStandardItem *item : row.items)
|
||||||
{
|
{
|
||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int rowCount(const QModelIndex &parent) const override
|
int rowCount(const QModelIndex &parent) const override
|
||||||
{
|
{
|
||||||
(void)parent;
|
(void)parent;
|
||||||
|
|
||||||
return this->rows_.size();
|
return this->rows_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
int columnCount(const QModelIndex &parent) const override
|
int columnCount(const QModelIndex &parent) const override
|
||||||
{
|
{
|
||||||
(void)parent;
|
(void)parent;
|
||||||
|
|
||||||
return this->columnCount_;
|
return this->columnCount_;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant data(const QModelIndex &index, int role) const override
|
QVariant data(const QModelIndex &index, int role) const override
|
||||||
{
|
{
|
||||||
int row = index.row(), column = index.column();
|
int row = index.row(), column = index.column();
|
||||||
if (row < 0 || column < 0 || row >= this->rows_.size() ||
|
if (row < 0 || column < 0 || row >= this->rows_.size() ||
|
||||||
column >= this->columnCount_)
|
column >= this->columnCount_)
|
||||||
{
|
{
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
return rows_[row].items[column]->data(role);
|
return rows_[row].items[column]->data(role);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setData(const QModelIndex &index, const QVariant &value,
|
bool setData(const QModelIndex &index, const QVariant &value,
|
||||||
int role) override
|
int role) override
|
||||||
{
|
{
|
||||||
int row = index.row(), column = index.column();
|
int row = index.row(), column = index.column();
|
||||||
if (row < 0 || column < 0 || row >= this->rows_.size() ||
|
if (row < 0 || column < 0 || row >= this->rows_.size() ||
|
||||||
column >= this->columnCount_)
|
column >= this->columnCount_)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Row &rowItem = this->rows_[row];
|
Row &rowItem = this->rows_[row];
|
||||||
|
|
||||||
rowItem.items[column]->setData(value, role);
|
rowItem.items[column]->setData(value, role);
|
||||||
|
|
||||||
if (rowItem.isCustomRow)
|
if (rowItem.isCustomRow)
|
||||||
{
|
{
|
||||||
this->customRowSetData(rowItem.items, column, value, role, row);
|
this->customRowSetData(rowItem.items, column, value, role, row);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int vecRow = this->getVectorIndexFromModelIndex(row);
|
int vecRow = this->getVectorIndexFromModelIndex(row);
|
||||||
this->vector_->removeItem(vecRow, this);
|
this->vector_->removeItem(vecRow, this);
|
||||||
|
|
||||||
assert(this->rows_[row].original);
|
assert(this->rows_[row].original);
|
||||||
TVectorItem item = this->getItemFromRow(
|
TVectorItem item = this->getItemFromRow(
|
||||||
this->rows_[row].items, this->rows_[row].original.get());
|
this->rows_[row].items, this->rows_[row].original.get());
|
||||||
this->vector_->insertItem(item, vecRow, this);
|
this->vector_->insertItem(item, vecRow, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant headerData(int section, Qt::Orientation orientation,
|
QVariant headerData(int section, Qt::Orientation orientation,
|
||||||
int role) const override
|
int role) const override
|
||||||
{
|
{
|
||||||
if (orientation != Qt::Horizontal)
|
if (orientation != Qt::Horizontal)
|
||||||
{
|
{
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = this->headerData_[section].find(role);
|
auto it = this->headerData_[section].find(role);
|
||||||
if (it == this->headerData_[section].end())
|
if (it == this->headerData_[section].end())
|
||||||
{
|
{
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return it.value();
|
return it.value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setHeaderData(int section, Qt::Orientation orientation,
|
bool setHeaderData(int section, Qt::Orientation orientation,
|
||||||
const QVariant &value,
|
const QVariant &value,
|
||||||
int role = Qt::DisplayRole) override
|
int role = Qt::DisplayRole) override
|
||||||
{
|
{
|
||||||
if (orientation != Qt::Horizontal)
|
if (orientation != Qt::Horizontal)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->headerData_[section][role] = value;
|
this->headerData_[section][role] = value;
|
||||||
|
|
||||||
emit this->headerDataChanged(Qt::Horizontal, section, section);
|
emit this->headerDataChanged(Qt::Horizontal, section, section);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::ItemFlags flags(const QModelIndex &index) const override
|
Qt::ItemFlags flags(const QModelIndex &index) const override
|
||||||
{
|
{
|
||||||
int row = index.row(), column = index.column();
|
int row = index.row(), column = index.column();
|
||||||
|
|
||||||
if (row < 0 || column < 0 || row >= this->rows_.size() ||
|
if (row < 0 || column < 0 || row >= this->rows_.size() ||
|
||||||
column >= this->columnCount_)
|
column >= this->columnCount_)
|
||||||
{
|
{
|
||||||
return Qt::NoItemFlags;
|
return Qt::NoItemFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(row >= 0 && row < this->rows_.size() && column >= 0 &&
|
assert(row >= 0 && row < this->rows_.size() && column >= 0 &&
|
||||||
column < this->columnCount_);
|
column < this->columnCount_);
|
||||||
|
|
||||||
return this->rows_[row].items[column]->flags();
|
return this->rows_[row].items[column]->flags();
|
||||||
}
|
}
|
||||||
|
|
||||||
QStandardItem *getItem(int row, int column)
|
QStandardItem *getItem(int row, int column)
|
||||||
{
|
{
|
||||||
assert(row >= 0 && row < this->rows_.size() && column >= 0 &&
|
assert(row >= 0 && row < this->rows_.size() && column >= 0 &&
|
||||||
column < this->columnCount_);
|
column < this->columnCount_);
|
||||||
|
|
||||||
return rows_[row].items[column];
|
return rows_[row].items[column];
|
||||||
}
|
}
|
||||||
|
|
||||||
void deleteRow(int row)
|
void deleteRow(int row)
|
||||||
{
|
{
|
||||||
int signalVectorRow = this->getVectorIndexFromModelIndex(row);
|
int signalVectorRow = this->getVectorIndexFromModelIndex(row);
|
||||||
this->vector_->removeItem(signalVectorRow);
|
this->vector_->removeItem(signalVectorRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool removeRows(int row, int count, const QModelIndex &parent) override
|
bool removeRows(int row, int count, const QModelIndex &parent) override
|
||||||
{
|
{
|
||||||
(void)parent;
|
(void)parent;
|
||||||
|
|
||||||
if (count != 1)
|
if (count != 1)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(row >= 0 && row < this->rows_.size());
|
assert(row >= 0 && row < this->rows_.size());
|
||||||
|
|
||||||
int signalVectorRow = this->getVectorIndexFromModelIndex(row);
|
int signalVectorRow = this->getVectorIndexFromModelIndex(row);
|
||||||
this->vector_->removeItem(signalVectorRow);
|
this->vector_->removeItem(signalVectorRow);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void afterInit()
|
virtual void afterInit()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// turn a vector item into a model row
|
// turn a vector item into a model row
|
||||||
virtual TVectorItem getItemFromRow(std::vector<QStandardItem *> &row,
|
virtual TVectorItem getItemFromRow(std::vector<QStandardItem *> &row,
|
||||||
const TVectorItem &original) = 0;
|
const TVectorItem &original) = 0;
|
||||||
|
|
||||||
// turns a row in the model into a vector item
|
// turns a row in the model into a vector item
|
||||||
virtual void getRowFromItem(const TVectorItem &item,
|
virtual void getRowFromItem(const TVectorItem &item,
|
||||||
std::vector<QStandardItem *> &row) = 0;
|
std::vector<QStandardItem *> &row) = 0;
|
||||||
|
|
||||||
virtual int beforeInsert(const TVectorItem &item,
|
virtual int beforeInsert(const TVectorItem &item,
|
||||||
std::vector<QStandardItem *> &row,
|
std::vector<QStandardItem *> &row,
|
||||||
int proposedIndex)
|
int proposedIndex)
|
||||||
{
|
{
|
||||||
(void)item, (void)row;
|
(void)item, (void)row;
|
||||||
|
|
||||||
return proposedIndex;
|
return proposedIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void afterRemoved(const TVectorItem &item,
|
virtual void afterRemoved(const TVectorItem &item,
|
||||||
std::vector<QStandardItem *> &row, int index)
|
std::vector<QStandardItem *> &row, int index)
|
||||||
{
|
{
|
||||||
(void)item, (void)row, (void)index;
|
(void)item, (void)row, (void)index;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void customRowSetData(const std::vector<QStandardItem *> &row,
|
virtual void customRowSetData(const std::vector<QStandardItem *> &row,
|
||||||
int column, const QVariant &value, int role,
|
int column, const QVariant &value, int role,
|
||||||
int rowIndex)
|
int rowIndex)
|
||||||
{
|
{
|
||||||
(void)row, (void)column, (void)value, (void)role, (void)rowIndex;
|
(void)row, (void)column, (void)value, (void)role, (void)rowIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertCustomRow(std::vector<QStandardItem *> row, int index)
|
void insertCustomRow(std::vector<QStandardItem *> row, int index)
|
||||||
{
|
{
|
||||||
assert(index >= 0 && index <= this->rows_.size());
|
assert(index >= 0 && index <= this->rows_.size());
|
||||||
|
|
||||||
this->beginInsertRows(QModelIndex(), index, index);
|
this->beginInsertRows(QModelIndex(), index, index);
|
||||||
this->rows_.insert(this->rows_.begin() + index,
|
this->rows_.insert(this->rows_.begin() + index,
|
||||||
Row(std::move(row), true));
|
Row(std::move(row), true));
|
||||||
this->endInsertRows();
|
this->endInsertRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeCustomRow(int index)
|
void removeCustomRow(int index)
|
||||||
{
|
{
|
||||||
assert(index >= 0 && index <= this->rows_.size());
|
assert(index >= 0 && index <= this->rows_.size());
|
||||||
assert(this->rows_[index].isCustomRow);
|
assert(this->rows_[index].isCustomRow);
|
||||||
|
|
||||||
this->beginRemoveRows(QModelIndex(), index, index);
|
this->beginRemoveRows(QModelIndex(), index, index);
|
||||||
this->rows_.erase(this->rows_.begin() + index);
|
this->rows_.erase(this->rows_.begin() + index);
|
||||||
this->endRemoveRows();
|
this->endRemoveRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<QStandardItem *> createRow()
|
std::vector<QStandardItem *> createRow()
|
||||||
{
|
{
|
||||||
std::vector<QStandardItem *> row;
|
std::vector<QStandardItem *> row;
|
||||||
for (int i = 0; i < this->columnCount_; i++)
|
for (int i = 0; i < this->columnCount_; i++)
|
||||||
{
|
{
|
||||||
row.push_back(new QStandardItem());
|
row.push_back(new QStandardItem());
|
||||||
}
|
}
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Row {
|
struct Row {
|
||||||
std::vector<QStandardItem *> items;
|
std::vector<QStandardItem *> items;
|
||||||
boost::optional<TVectorItem> original;
|
boost::optional<TVectorItem> original;
|
||||||
bool isCustomRow;
|
bool isCustomRow;
|
||||||
|
|
||||||
Row(std::vector<QStandardItem *> _items, bool _isCustomRow = false)
|
Row(std::vector<QStandardItem *> _items, bool _isCustomRow = false)
|
||||||
: items(std::move(_items))
|
: items(std::move(_items))
|
||||||
, isCustomRow(_isCustomRow)
|
, isCustomRow(_isCustomRow)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(std::vector<QStandardItem *> _items, const TVectorItem &_original,
|
Row(std::vector<QStandardItem *> _items, const TVectorItem &_original,
|
||||||
bool _isCustomRow = false)
|
bool _isCustomRow = false)
|
||||||
: items(std::move(_items))
|
: items(std::move(_items))
|
||||||
, original(_original)
|
, original(_original)
|
||||||
, isCustomRow(_isCustomRow)
|
, isCustomRow(_isCustomRow)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<QMap<int, QVariant>> headerData_;
|
std::vector<QMap<int, QVariant>> headerData_;
|
||||||
BaseSignalVector<TVectorItem> *vector_;
|
BaseSignalVector<TVectorItem> *vector_;
|
||||||
std::vector<Row> rows_;
|
std::vector<Row> rows_;
|
||||||
|
|
||||||
int columnCount_;
|
int columnCount_;
|
||||||
|
|
||||||
// returns the related index of the SignalVector
|
// returns the related index of the SignalVector
|
||||||
int getVectorIndexFromModelIndex(int index)
|
int getVectorIndexFromModelIndex(int index)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
for (auto &row : this->rows_)
|
for (auto &row : this->rows_)
|
||||||
{
|
{
|
||||||
if (row.isCustomRow)
|
if (row.isCustomRow)
|
||||||
{
|
{
|
||||||
index--;
|
index--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == index)
|
if (i == index)
|
||||||
{
|
{
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the related index of the model
|
// returns the related index of the model
|
||||||
int getModelIndexFromVectorIndex(int index)
|
int getModelIndexFromVectorIndex(int index)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
for (auto &row : this->rows_)
|
for (auto &row : this->rows_)
|
||||||
{
|
{
|
||||||
if (row.isCustomRow)
|
if (row.isCustomRow)
|
||||||
{
|
{
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == index)
|
if (i == index)
|
||||||
{
|
{
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
+125
-125
@@ -1,125 +1,125 @@
|
|||||||
#include "UsernameSet.hpp"
|
#include "UsernameSet.hpp"
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
//
|
//
|
||||||
// UsernameSet
|
// UsernameSet
|
||||||
//
|
//
|
||||||
|
|
||||||
UsernameSet::ConstIterator UsernameSet::begin() const
|
UsernameSet::ConstIterator UsernameSet::begin() const
|
||||||
{
|
{
|
||||||
return this->items.begin();
|
return this->items.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
UsernameSet::ConstIterator UsernameSet::end() const
|
UsernameSet::ConstIterator UsernameSet::end() const
|
||||||
{
|
{
|
||||||
return this->items.end();
|
return this->items.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
UsernameSet::Range UsernameSet::subrange(const Prefix &prefix) const
|
UsernameSet::Range UsernameSet::subrange(const Prefix &prefix) const
|
||||||
{
|
{
|
||||||
auto it = this->firstKeyForPrefix.find(prefix);
|
auto it = this->firstKeyForPrefix.find(prefix);
|
||||||
if (it != this->firstKeyForPrefix.end())
|
if (it != this->firstKeyForPrefix.end())
|
||||||
{
|
{
|
||||||
auto start = this->items.find(it->second);
|
auto start = this->items.find(it->second);
|
||||||
auto end = start;
|
auto end = start;
|
||||||
|
|
||||||
while (end != this->items.end() && prefix.isStartOf(*end))
|
while (end != this->items.end() && prefix.isStartOf(*end))
|
||||||
{
|
{
|
||||||
end++;
|
end++;
|
||||||
}
|
}
|
||||||
return {start, end};
|
return {start, end};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {this->items.end(), this->items.end()};
|
return {this->items.end(), this->items.end()};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<QString>::size_type UsernameSet::size() const
|
std::set<QString>::size_type UsernameSet::size() const
|
||||||
{
|
{
|
||||||
return this->items.size();
|
return this->items.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<UsernameSet::Iterator, bool> UsernameSet::insert(const QString &value)
|
std::pair<UsernameSet::Iterator, bool> UsernameSet::insert(const QString &value)
|
||||||
{
|
{
|
||||||
this->insertPrefix(value);
|
this->insertPrefix(value);
|
||||||
|
|
||||||
return this->items.insert(value);
|
return this->items.insert(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<UsernameSet::Iterator, bool> UsernameSet::insert(QString &&value)
|
std::pair<UsernameSet::Iterator, bool> UsernameSet::insert(QString &&value)
|
||||||
{
|
{
|
||||||
this->insertPrefix(value);
|
this->insertPrefix(value);
|
||||||
|
|
||||||
return this->items.insert(std::move(value));
|
return this->items.insert(std::move(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void UsernameSet::insertPrefix(const QString &value)
|
void UsernameSet::insertPrefix(const QString &value)
|
||||||
{
|
{
|
||||||
auto &string = this->firstKeyForPrefix[Prefix(value)];
|
auto &string = this->firstKeyForPrefix[Prefix(value)];
|
||||||
|
|
||||||
if (string.isNull() || value.compare(string, Qt::CaseInsensitive) < 0)
|
if (string.isNull() || value.compare(string, Qt::CaseInsensitive) < 0)
|
||||||
string = value;
|
string = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Range
|
// Range
|
||||||
//
|
//
|
||||||
|
|
||||||
UsernameSet::Range::Range(ConstIterator start, ConstIterator end)
|
UsernameSet::Range::Range(ConstIterator start, ConstIterator end)
|
||||||
: start_(start)
|
: start_(start)
|
||||||
, end_(end)
|
, end_(end)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
UsernameSet::ConstIterator UsernameSet::Range::begin()
|
UsernameSet::ConstIterator UsernameSet::Range::begin()
|
||||||
{
|
{
|
||||||
return this->start_;
|
return this->start_;
|
||||||
}
|
}
|
||||||
|
|
||||||
UsernameSet::ConstIterator UsernameSet::Range::end()
|
UsernameSet::ConstIterator UsernameSet::Range::end()
|
||||||
{
|
{
|
||||||
return this->end_;
|
return this->end_;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Prefix
|
// Prefix
|
||||||
//
|
//
|
||||||
|
|
||||||
Prefix::Prefix(const QString &string)
|
Prefix::Prefix(const QString &string)
|
||||||
: first(string.size() >= 1 ? string[0].toLower() : '\0')
|
: first(string.size() >= 1 ? string[0].toLower() : '\0')
|
||||||
, second(string.size() >= 2 ? string[1].toLower() : '\0')
|
, second(string.size() >= 2 ? string[1].toLower() : '\0')
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Prefix::operator==(const Prefix &other) const
|
bool Prefix::operator==(const Prefix &other) const
|
||||||
{
|
{
|
||||||
return std::tie(this->first, this->second) ==
|
return std::tie(this->first, this->second) ==
|
||||||
std::tie(other.first, other.second);
|
std::tie(other.first, other.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Prefix::operator!=(const Prefix &other) const
|
bool Prefix::operator!=(const Prefix &other) const
|
||||||
{
|
{
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Prefix::isStartOf(const QString &string) const
|
bool Prefix::isStartOf(const QString &string) const
|
||||||
{
|
{
|
||||||
if (string.size() == 0)
|
if (string.size() == 0)
|
||||||
{
|
{
|
||||||
return this->first == QChar('\0') && this->second == QChar('\0');
|
return this->first == QChar('\0') && this->second == QChar('\0');
|
||||||
}
|
}
|
||||||
else if (string.size() == 1)
|
else if (string.size() == 1)
|
||||||
{
|
{
|
||||||
return this->first == string[0].toLower() &&
|
return this->first == string[0].toLower() &&
|
||||||
this->second == QChar('\0');
|
this->second == QChar('\0');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return this->first == string[0].toLower() &&
|
return this->first == string[0].toLower() &&
|
||||||
this->second == string[1].toLower();
|
this->second == string[1].toLower();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
+86
-86
@@ -1,86 +1,86 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class Prefix
|
class Prefix
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Prefix(const QString &string);
|
Prefix(const QString &string);
|
||||||
bool operator==(const Prefix &other) const;
|
bool operator==(const Prefix &other) const;
|
||||||
bool operator!=(const Prefix &other) const;
|
bool operator!=(const Prefix &other) const;
|
||||||
bool isStartOf(const QString &string) const;
|
bool isStartOf(const QString &string) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QChar first;
|
QChar first;
|
||||||
QChar second;
|
QChar second;
|
||||||
|
|
||||||
friend struct std::hash<Prefix>;
|
friend struct std::hash<Prefix>;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct hash<chatterino::Prefix> {
|
struct hash<chatterino::Prefix> {
|
||||||
size_t operator()(const chatterino::Prefix &prefix) const
|
size_t operator()(const chatterino::Prefix &prefix) const
|
||||||
{
|
{
|
||||||
return (size_t(prefix.first.unicode()) << 16) |
|
return (size_t(prefix.first.unicode()) << 16) |
|
||||||
size_t(prefix.second.unicode());
|
size_t(prefix.second.unicode());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
struct CaseInsensitiveLess {
|
struct CaseInsensitiveLess {
|
||||||
bool operator()(const QString &lhs, const QString &rhs) const
|
bool operator()(const QString &lhs, const QString &rhs) const
|
||||||
{
|
{
|
||||||
return lhs.compare(rhs, Qt::CaseInsensitive) < 0;
|
return lhs.compare(rhs, Qt::CaseInsensitive) < 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class UsernameSet
|
class UsernameSet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr int PrefixLength = 2;
|
static constexpr int PrefixLength = 2;
|
||||||
|
|
||||||
using Iterator = std::set<QString>::iterator;
|
using Iterator = std::set<QString>::iterator;
|
||||||
using ConstIterator = std::set<QString>::const_iterator;
|
using ConstIterator = std::set<QString>::const_iterator;
|
||||||
|
|
||||||
class Range
|
class Range
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Range(ConstIterator start, ConstIterator end);
|
Range(ConstIterator start, ConstIterator end);
|
||||||
|
|
||||||
ConstIterator begin();
|
ConstIterator begin();
|
||||||
ConstIterator end();
|
ConstIterator end();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConstIterator start_;
|
ConstIterator start_;
|
||||||
ConstIterator end_;
|
ConstIterator end_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ConstIterator begin() const;
|
ConstIterator begin() const;
|
||||||
ConstIterator end() const;
|
ConstIterator end() const;
|
||||||
Range subrange(const Prefix &prefix) const;
|
Range subrange(const Prefix &prefix) const;
|
||||||
|
|
||||||
std::set<QString>::size_type size() const;
|
std::set<QString>::size_type size() const;
|
||||||
|
|
||||||
std::pair<Iterator, bool> insert(const QString &value);
|
std::pair<Iterator, bool> insert(const QString &value);
|
||||||
std::pair<Iterator, bool> insert(QString &&value);
|
std::pair<Iterator, bool> insert(QString &&value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void insertPrefix(const QString &string);
|
void insertPrefix(const QString &string);
|
||||||
|
|
||||||
std::set<QString, CaseInsensitiveLess> items;
|
std::set<QString, CaseInsensitiveLess> items;
|
||||||
std::unordered_map<Prefix, QString> firstKeyForPrefix;
|
std::unordered_map<Prefix, QString> firstKeyForPrefix;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
+15
-15
@@ -1,15 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
|
|
||||||
#define CHATTERINO_VERSION "2.1.4-beta-1"
|
#define CHATTERINO_VERSION "2.1.4"
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
# define CHATTERINO_OS "win"
|
# define CHATTERINO_OS "win"
|
||||||
#elif defined(Q_OS_MACOS)
|
#elif defined(Q_OS_MACOS)
|
||||||
# define CHATTERINO_OS "macos"
|
# define CHATTERINO_OS "macos"
|
||||||
#elif defined(Q_OS_LINUX)
|
#elif defined(Q_OS_LINUX)
|
||||||
# define CHATTERINO_OS "linux"
|
# define CHATTERINO_OS "linux"
|
||||||
#else
|
#else
|
||||||
# define CHATTERINO_OS "unknown"
|
# define CHATTERINO_OS "unknown"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,40 +1,40 @@
|
|||||||
#include "Account.hpp"
|
#include "Account.hpp"
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
Account::Account(ProviderId providerId)
|
Account::Account(ProviderId providerId)
|
||||||
: providerId_(providerId)
|
: providerId_(providerId)
|
||||||
{
|
{
|
||||||
static QString twitch("Twitch");
|
static QString twitch("Twitch");
|
||||||
|
|
||||||
this->category_ = [&]() {
|
this->category_ = [&]() {
|
||||||
switch (providerId)
|
switch (providerId)
|
||||||
{
|
{
|
||||||
case ProviderId::Twitch:
|
case ProviderId::Twitch:
|
||||||
return twitch;
|
return twitch;
|
||||||
}
|
}
|
||||||
return QString("Unknown ProviderId");
|
return QString("Unknown ProviderId");
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString &Account::getCategory() const
|
const QString &Account::getCategory() const
|
||||||
{
|
{
|
||||||
return this->category_;
|
return this->category_;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProviderId Account::getProviderId() const
|
ProviderId Account::getProviderId() const
|
||||||
{
|
{
|
||||||
return this->providerId_;
|
return this->providerId_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Account::operator<(const Account &other) const
|
bool Account::operator<(const Account &other) const
|
||||||
{
|
{
|
||||||
QString a = this->toString();
|
QString a = this->toString();
|
||||||
QString b = other.toString();
|
QString b = other.toString();
|
||||||
|
|
||||||
return std::tie(this->category_, a) < std::tie(other.category_, b);
|
return std::tie(this->category_, a) < std::tie(other.category_, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/ProviderId.hpp"
|
#include "common/ProviderId.hpp"
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class Account
|
class Account
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Account(ProviderId providerId);
|
Account(ProviderId providerId);
|
||||||
virtual ~Account() = default;
|
virtual ~Account() = default;
|
||||||
|
|
||||||
virtual QString toString() const = 0;
|
virtual QString toString() const = 0;
|
||||||
const QString &getCategory() const;
|
const QString &getCategory() const;
|
||||||
ProviderId getProviderId() const;
|
ProviderId getProviderId() const;
|
||||||
|
|
||||||
bool operator<(const Account &other) const;
|
bool operator<(const Account &other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProviderId providerId_;
|
ProviderId providerId_;
|
||||||
QString category_;
|
QString category_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,58 +1,58 @@
|
|||||||
#include "AccountController.hpp"
|
#include "AccountController.hpp"
|
||||||
|
|
||||||
#include "controllers/accounts/Account.hpp"
|
#include "controllers/accounts/Account.hpp"
|
||||||
#include "controllers/accounts/AccountModel.hpp"
|
#include "controllers/accounts/AccountModel.hpp"
|
||||||
#include "providers/twitch/TwitchAccount.hpp"
|
#include "providers/twitch/TwitchAccount.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
AccountController::AccountController()
|
AccountController::AccountController()
|
||||||
{
|
{
|
||||||
this->twitch.accounts.itemInserted.connect([this](const auto &args) {
|
this->twitch.accounts.itemInserted.connect([this](const auto &args) {
|
||||||
this->accounts_.insertItem(
|
this->accounts_.insertItem(
|
||||||
std::dynamic_pointer_cast<Account>(args.item));
|
std::dynamic_pointer_cast<Account>(args.item));
|
||||||
});
|
});
|
||||||
|
|
||||||
this->twitch.accounts.itemRemoved.connect([this](const auto &args) {
|
this->twitch.accounts.itemRemoved.connect([this](const auto &args) {
|
||||||
if (args.caller != this)
|
if (args.caller != this)
|
||||||
{
|
{
|
||||||
auto &accs = this->twitch.accounts.getVector();
|
auto &accs = this->twitch.accounts.getVector();
|
||||||
auto it = std::find(accs.begin(), accs.end(), args.item);
|
auto it = std::find(accs.begin(), accs.end(), args.item);
|
||||||
assert(it != accs.end());
|
assert(it != accs.end());
|
||||||
|
|
||||||
this->accounts_.removeItem(it - accs.begin(), this);
|
this->accounts_.removeItem(it - accs.begin(), this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this->accounts_.itemRemoved.connect([this](const auto &args) {
|
this->accounts_.itemRemoved.connect([this](const auto &args) {
|
||||||
switch (args.item->getProviderId())
|
switch (args.item->getProviderId())
|
||||||
{
|
{
|
||||||
case ProviderId::Twitch:
|
case ProviderId::Twitch:
|
||||||
{
|
{
|
||||||
if (args.caller != this)
|
if (args.caller != this)
|
||||||
{
|
{
|
||||||
auto accs = this->twitch.accounts.cloneVector();
|
auto accs = this->twitch.accounts.cloneVector();
|
||||||
auto it = std::find(accs.begin(), accs.end(), args.item);
|
auto it = std::find(accs.begin(), accs.end(), args.item);
|
||||||
assert(it != accs.end());
|
assert(it != accs.end());
|
||||||
this->twitch.accounts.removeItem(it - accs.begin(), this);
|
this->twitch.accounts.removeItem(it - accs.begin(), this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountController::initialize(Settings &settings, Paths &paths)
|
void AccountController::initialize(Settings &settings, Paths &paths)
|
||||||
{
|
{
|
||||||
this->twitch.load();
|
this->twitch.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
AccountModel *AccountController::createModel(QObject *parent)
|
AccountModel *AccountController::createModel(QObject *parent)
|
||||||
{
|
{
|
||||||
AccountModel *model = new AccountModel(parent);
|
AccountModel *model = new AccountModel(parent);
|
||||||
|
|
||||||
model->init(&this->accounts_);
|
model->init(&this->accounts_);
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,34 +1,34 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "common/SignalVector.hpp"
|
#include "common/SignalVector.hpp"
|
||||||
#include "common/Singleton.hpp"
|
#include "common/Singleton.hpp"
|
||||||
#include "providers/twitch/TwitchAccountManager.hpp"
|
#include "providers/twitch/TwitchAccountManager.hpp"
|
||||||
#include "util/SharedPtrElementLess.hpp"
|
#include "util/SharedPtrElementLess.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class Account;
|
class Account;
|
||||||
class Settings;
|
class Settings;
|
||||||
class Paths;
|
class Paths;
|
||||||
|
|
||||||
class AccountModel;
|
class AccountModel;
|
||||||
|
|
||||||
class AccountController final : public Singleton
|
class AccountController final : public Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AccountController();
|
AccountController();
|
||||||
|
|
||||||
AccountModel *createModel(QObject *parent);
|
AccountModel *createModel(QObject *parent);
|
||||||
|
|
||||||
virtual void initialize(Settings &settings, Paths &paths) override;
|
virtual void initialize(Settings &settings, Paths &paths) override;
|
||||||
|
|
||||||
TwitchAccountManager twitch;
|
TwitchAccountManager twitch;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SortedSignalVector<std::shared_ptr<Account>, SharedPtrElementLess<Account>>
|
SortedSignalVector<std::shared_ptr<Account>, SharedPtrElementLess<Account>>
|
||||||
accounts_;
|
accounts_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,64 +1,64 @@
|
|||||||
#include "AccountModel.hpp"
|
#include "AccountModel.hpp"
|
||||||
|
|
||||||
#include "controllers/accounts/Account.hpp"
|
#include "controllers/accounts/Account.hpp"
|
||||||
#include "util/StandardItemHelper.hpp"
|
#include "util/StandardItemHelper.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
AccountModel::AccountModel(QObject *parent)
|
AccountModel::AccountModel(QObject *parent)
|
||||||
: SignalVectorModel<std::shared_ptr<Account>>(1, parent)
|
: SignalVectorModel<std::shared_ptr<Account>>(1, parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// turn a vector item into a model row
|
// turn a vector item into a model row
|
||||||
std::shared_ptr<Account> AccountModel::getItemFromRow(
|
std::shared_ptr<Account> AccountModel::getItemFromRow(
|
||||||
std::vector<QStandardItem *> &, const std::shared_ptr<Account> &original)
|
std::vector<QStandardItem *> &, const std::shared_ptr<Account> &original)
|
||||||
{
|
{
|
||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
|
|
||||||
// turns a row in the model into a vector item
|
// turns a row in the model into a vector item
|
||||||
void AccountModel::getRowFromItem(const std::shared_ptr<Account> &item,
|
void AccountModel::getRowFromItem(const std::shared_ptr<Account> &item,
|
||||||
std::vector<QStandardItem *> &row)
|
std::vector<QStandardItem *> &row)
|
||||||
{
|
{
|
||||||
setStringItem(row[0], item->toString(), false);
|
setStringItem(row[0], item->toString(), false);
|
||||||
row[0]->setData(QFont("Segoe UI", 10), Qt::FontRole);
|
row[0]->setData(QFont("Segoe UI", 10), Qt::FontRole);
|
||||||
}
|
}
|
||||||
|
|
||||||
int AccountModel::beforeInsert(const std::shared_ptr<Account> &item,
|
int AccountModel::beforeInsert(const std::shared_ptr<Account> &item,
|
||||||
std::vector<QStandardItem *> &row,
|
std::vector<QStandardItem *> &row,
|
||||||
int proposedIndex)
|
int proposedIndex)
|
||||||
{
|
{
|
||||||
if (this->categoryCount_[item->getCategory()]++ == 0)
|
if (this->categoryCount_[item->getCategory()]++ == 0)
|
||||||
{
|
{
|
||||||
auto newRow = this->createRow();
|
auto newRow = this->createRow();
|
||||||
|
|
||||||
setStringItem(newRow[0], item->getCategory(), false, false);
|
setStringItem(newRow[0], item->getCategory(), false, false);
|
||||||
newRow[0]->setData(QFont("Segoe UI Light", 16), Qt::FontRole);
|
newRow[0]->setData(QFont("Segoe UI Light", 16), Qt::FontRole);
|
||||||
|
|
||||||
this->insertCustomRow(std::move(newRow), proposedIndex);
|
this->insertCustomRow(std::move(newRow), proposedIndex);
|
||||||
|
|
||||||
return proposedIndex + 1;
|
return proposedIndex + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return proposedIndex;
|
return proposedIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountModel::afterRemoved(const std::shared_ptr<Account> &item,
|
void AccountModel::afterRemoved(const std::shared_ptr<Account> &item,
|
||||||
std::vector<QStandardItem *> &row, int index)
|
std::vector<QStandardItem *> &row, int index)
|
||||||
{
|
{
|
||||||
auto it = this->categoryCount_.find(item->getCategory());
|
auto it = this->categoryCount_.find(item->getCategory());
|
||||||
assert(it != this->categoryCount_.end());
|
assert(it != this->categoryCount_.end());
|
||||||
|
|
||||||
if (it->second <= 1)
|
if (it->second <= 1)
|
||||||
{
|
{
|
||||||
this->categoryCount_.erase(it);
|
this->categoryCount_.erase(it);
|
||||||
this->removeCustomRow(index - 1);
|
this->removeCustomRow(index - 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
it->second--;
|
it->second--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,43 +1,43 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/SignalVectorModel.hpp"
|
#include "common/SignalVectorModel.hpp"
|
||||||
#include "controllers/accounts/Account.hpp"
|
#include "controllers/accounts/Account.hpp"
|
||||||
#include "util/QStringHash.hpp"
|
#include "util/QStringHash.hpp"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class Account;
|
class Account;
|
||||||
class AccountController;
|
class AccountController;
|
||||||
|
|
||||||
class AccountModel : public SignalVectorModel<std::shared_ptr<Account>>
|
class AccountModel : public SignalVectorModel<std::shared_ptr<Account>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AccountModel(QObject *parent);
|
AccountModel(QObject *parent);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// turn a vector item into a model row
|
// turn a vector item into a model row
|
||||||
virtual std::shared_ptr<Account> getItemFromRow(
|
virtual std::shared_ptr<Account> getItemFromRow(
|
||||||
std::vector<QStandardItem *> &row,
|
std::vector<QStandardItem *> &row,
|
||||||
const std::shared_ptr<Account> &original) override;
|
const std::shared_ptr<Account> &original) override;
|
||||||
|
|
||||||
// turns a row in the model into a vector item
|
// turns a row in the model into a vector item
|
||||||
virtual void getRowFromItem(const std::shared_ptr<Account> &item,
|
virtual void getRowFromItem(const std::shared_ptr<Account> &item,
|
||||||
std::vector<QStandardItem *> &row) override;
|
std::vector<QStandardItem *> &row) override;
|
||||||
|
|
||||||
virtual int beforeInsert(const std::shared_ptr<Account> &item,
|
virtual int beforeInsert(const std::shared_ptr<Account> &item,
|
||||||
std::vector<QStandardItem *> &row,
|
std::vector<QStandardItem *> &row,
|
||||||
int proposedIndex) override;
|
int proposedIndex) override;
|
||||||
|
|
||||||
virtual void afterRemoved(const std::shared_ptr<Account> &item,
|
virtual void afterRemoved(const std::shared_ptr<Account> &item,
|
||||||
std::vector<QStandardItem *> &row,
|
std::vector<QStandardItem *> &row,
|
||||||
int index) override;
|
int index) override;
|
||||||
|
|
||||||
friend class AccountController;
|
friend class AccountController;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<QString, int> categoryCount_;
|
std::unordered_map<QString, int> categoryCount_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
#include "Command.hpp"
|
#include "Command.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
// command
|
// command
|
||||||
Command::Command(const QString &_text)
|
Command::Command(const QString &_text)
|
||||||
{
|
{
|
||||||
int index = _text.indexOf(' ');
|
int index = _text.indexOf(' ');
|
||||||
|
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
{
|
{
|
||||||
this->name = _text;
|
this->name = _text;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->name = _text.mid(0, index).trimmed();
|
this->name = _text.mid(0, index).trimmed();
|
||||||
this->func = _text.mid(index + 1).trimmed();
|
this->func = _text.mid(index + 1).trimmed();
|
||||||
}
|
}
|
||||||
|
|
||||||
Command::Command(const QString &_name, const QString &_func)
|
Command::Command(const QString &_name, const QString &_func)
|
||||||
: name(_name.trimmed())
|
: name(_name.trimmed())
|
||||||
, func(_func.trimmed())
|
, func(_func.trimmed())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Command::toString() const
|
QString Command::toString() const
|
||||||
{
|
{
|
||||||
return this->name + " " + this->func;
|
return this->name + " " + this->func;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,67 +1,67 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/RapidjsonHelpers.hpp"
|
#include "util/RapidjsonHelpers.hpp"
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <pajlada/serialize.hpp>
|
#include <pajlada/serialize.hpp>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
struct Command {
|
struct Command {
|
||||||
QString name;
|
QString name;
|
||||||
QString func;
|
QString func;
|
||||||
|
|
||||||
Command() = default;
|
Command() = default;
|
||||||
explicit Command(const QString &text);
|
explicit Command(const QString &text);
|
||||||
Command(const QString &name, const QString &func);
|
Command(const QString &name, const QString &func);
|
||||||
|
|
||||||
QString toString() const;
|
QString toString() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
||||||
namespace pajlada {
|
namespace pajlada {
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct Serialize<chatterino::Command> {
|
struct Serialize<chatterino::Command> {
|
||||||
static rapidjson::Value get(const chatterino::Command &value,
|
static rapidjson::Value get(const chatterino::Command &value,
|
||||||
rapidjson::Document::AllocatorType &a)
|
rapidjson::Document::AllocatorType &a)
|
||||||
{
|
{
|
||||||
rapidjson::Value ret(rapidjson::kObjectType);
|
rapidjson::Value ret(rapidjson::kObjectType);
|
||||||
|
|
||||||
chatterino::rj::set(ret, "name", value.name, a);
|
chatterino::rj::set(ret, "name", value.name, a);
|
||||||
chatterino::rj::set(ret, "func", value.func, a);
|
chatterino::rj::set(ret, "func", value.func, a);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct Deserialize<chatterino::Command> {
|
struct Deserialize<chatterino::Command> {
|
||||||
static chatterino::Command get(const rapidjson::Value &value,
|
static chatterino::Command get(const rapidjson::Value &value,
|
||||||
bool *error = nullptr)
|
bool *error = nullptr)
|
||||||
{
|
{
|
||||||
chatterino::Command command;
|
chatterino::Command command;
|
||||||
|
|
||||||
if (!value.IsObject())
|
if (!value.IsObject())
|
||||||
{
|
{
|
||||||
PAJLADA_REPORT_ERROR(error);
|
PAJLADA_REPORT_ERROR(error);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!chatterino::rj::getSafe(value, "name", command.name))
|
if (!chatterino::rj::getSafe(value, "name", command.name))
|
||||||
{
|
{
|
||||||
PAJLADA_REPORT_ERROR(error);
|
PAJLADA_REPORT_ERROR(error);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
if (!chatterino::rj::getSafe(value, "func", command.func))
|
if (!chatterino::rj::getSafe(value, "func", command.func))
|
||||||
{
|
{
|
||||||
PAJLADA_REPORT_ERROR(error);
|
PAJLADA_REPORT_ERROR(error);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pajlada
|
} // namespace pajlada
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,56 +1,56 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/ChatterinoSetting.hpp"
|
#include "common/ChatterinoSetting.hpp"
|
||||||
#include "common/SignalVector.hpp"
|
#include "common/SignalVector.hpp"
|
||||||
#include "common/Singleton.hpp"
|
#include "common/Singleton.hpp"
|
||||||
#include "controllers/commands/Command.hpp"
|
#include "controllers/commands/Command.hpp"
|
||||||
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <pajlada/settings.hpp>
|
#include <pajlada/settings.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class Settings;
|
class Settings;
|
||||||
class Paths;
|
class Paths;
|
||||||
class Channel;
|
class Channel;
|
||||||
|
|
||||||
class CommandModel;
|
class CommandModel;
|
||||||
|
|
||||||
class CommandController final : public Singleton
|
class CommandController final : public Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
UnsortedSignalVector<Command> items_;
|
UnsortedSignalVector<Command> items_;
|
||||||
|
|
||||||
QString execCommand(const QString &text, std::shared_ptr<Channel> channel,
|
QString execCommand(const QString &text, std::shared_ptr<Channel> channel,
|
||||||
bool dryRun);
|
bool dryRun);
|
||||||
QStringList getDefaultTwitchCommandList();
|
QStringList getDefaultTwitchCommandList();
|
||||||
|
|
||||||
virtual void initialize(Settings &, Paths &paths) override;
|
virtual void initialize(Settings &, Paths &paths) override;
|
||||||
virtual void save() override;
|
virtual void save() override;
|
||||||
|
|
||||||
CommandModel *createModel(QObject *parent);
|
CommandModel *createModel(QObject *parent);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void load(Paths &paths);
|
void load(Paths &paths);
|
||||||
|
|
||||||
QMap<QString, Command> commandsMap_;
|
QMap<QString, Command> commandsMap_;
|
||||||
int maxSpaces_ = 0;
|
int maxSpaces_ = 0;
|
||||||
|
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
|
|
||||||
std::shared_ptr<pajlada::Settings::SettingManager> sm_;
|
std::shared_ptr<pajlada::Settings::SettingManager> sm_;
|
||||||
// Because the setting manager is not initialized until the initialize
|
// Because the setting manager is not initialized until the initialize
|
||||||
// function is called (and not in the constructor), we have to
|
// function is called (and not in the constructor), we have to
|
||||||
// late-initialize the setting, which is why we're storing it as a
|
// late-initialize the setting, which is why we're storing it as a
|
||||||
// unique_ptr
|
// unique_ptr
|
||||||
std::unique_ptr<pajlada::Settings::Setting<std::vector<Command>>>
|
std::unique_ptr<pajlada::Settings::Setting<std::vector<Command>>>
|
||||||
commandsSetting_;
|
commandsSetting_;
|
||||||
|
|
||||||
QString execCustomCommand(const QStringList &words, const Command &command,
|
QString execCustomCommand(const QStringList &words, const Command &command,
|
||||||
bool dryRun);
|
bool dryRun);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
#include "CommandModel.hpp"
|
#include "CommandModel.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
// commandmodel
|
// commandmodel
|
||||||
CommandModel::CommandModel(QObject *parent)
|
CommandModel::CommandModel(QObject *parent)
|
||||||
: SignalVectorModel<Command>(2, parent)
|
: SignalVectorModel<Command>(2, parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// turn a vector item into a model row
|
// turn a vector item into a model row
|
||||||
Command CommandModel::getItemFromRow(std::vector<QStandardItem *> &row,
|
Command CommandModel::getItemFromRow(std::vector<QStandardItem *> &row,
|
||||||
const Command &original)
|
const Command &original)
|
||||||
{
|
{
|
||||||
return Command(row[0]->data(Qt::EditRole).toString(),
|
return Command(row[0]->data(Qt::EditRole).toString(),
|
||||||
row[1]->data(Qt::EditRole).toString());
|
row[1]->data(Qt::EditRole).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// turns a row in the model into a vector item
|
// turns a row in the model into a vector item
|
||||||
void CommandModel::getRowFromItem(const Command &item,
|
void CommandModel::getRowFromItem(const Command &item,
|
||||||
std::vector<QStandardItem *> &row)
|
std::vector<QStandardItem *> &row)
|
||||||
{
|
{
|
||||||
row[0]->setData(item.name, Qt::DisplayRole);
|
row[0]->setData(item.name, Qt::DisplayRole);
|
||||||
row[0]->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable |
|
row[0]->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable |
|
||||||
Qt::ItemIsEditable);
|
Qt::ItemIsEditable);
|
||||||
row[1]->setData(item.func, Qt::DisplayRole);
|
row[1]->setData(item.func, Qt::DisplayRole);
|
||||||
row[1]->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable |
|
row[1]->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable |
|
||||||
Qt::ItemIsEditable);
|
Qt::ItemIsEditable);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "common/SignalVectorModel.hpp"
|
#include "common/SignalVectorModel.hpp"
|
||||||
#include "controllers/commands/Command.hpp"
|
#include "controllers/commands/Command.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class CommandController;
|
class CommandController;
|
||||||
|
|
||||||
class CommandModel : public SignalVectorModel<Command>
|
class CommandModel : public SignalVectorModel<Command>
|
||||||
{
|
{
|
||||||
explicit CommandModel(QObject *parent);
|
explicit CommandModel(QObject *parent);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// turn a vector item into a model row
|
// turn a vector item into a model row
|
||||||
virtual Command getItemFromRow(std::vector<QStandardItem *> &row,
|
virtual Command getItemFromRow(std::vector<QStandardItem *> &row,
|
||||||
const Command &command) override;
|
const Command &command) override;
|
||||||
|
|
||||||
// turns a row in the model into a vector item
|
// turns a row in the model into a vector item
|
||||||
virtual void getRowFromItem(const Command &item,
|
virtual void getRowFromItem(const Command &item,
|
||||||
std::vector<QStandardItem *> &row) override;
|
std::vector<QStandardItem *> &row) override;
|
||||||
|
|
||||||
friend class CommandController;
|
friend class CommandController;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,110 +1,110 @@
|
|||||||
#include "HighlightController.hpp"
|
#include "HighlightController.hpp"
|
||||||
|
|
||||||
#include "Application.hpp"
|
#include "Application.hpp"
|
||||||
#include "controllers/highlights/HighlightBlacklistModel.hpp"
|
#include "controllers/highlights/HighlightBlacklistModel.hpp"
|
||||||
#include "controllers/highlights/HighlightModel.hpp"
|
#include "controllers/highlights/HighlightModel.hpp"
|
||||||
#include "controllers/highlights/UserHighlightModel.hpp"
|
#include "controllers/highlights/UserHighlightModel.hpp"
|
||||||
#include "widgets/dialogs/NotificationPopup.hpp"
|
#include "widgets/dialogs/NotificationPopup.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
HighlightController::HighlightController()
|
HighlightController::HighlightController()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void HighlightController::initialize(Settings &settings, Paths &paths)
|
void HighlightController::initialize(Settings &settings, Paths &paths)
|
||||||
{
|
{
|
||||||
assert(!this->initialized_);
|
assert(!this->initialized_);
|
||||||
this->initialized_ = true;
|
this->initialized_ = true;
|
||||||
|
|
||||||
for (const HighlightPhrase &phrase : this->highlightsSetting_.getValue())
|
for (const HighlightPhrase &phrase : this->highlightsSetting_.getValue())
|
||||||
{
|
{
|
||||||
this->phrases.appendItem(phrase);
|
this->phrases.appendItem(phrase);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->phrases.delayedItemsChanged.connect([this] { //
|
this->phrases.delayedItemsChanged.connect([this] { //
|
||||||
this->highlightsSetting_.setValue(this->phrases.getVector());
|
this->highlightsSetting_.setValue(this->phrases.getVector());
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const HighlightBlacklistUser &blacklistedUser :
|
for (const HighlightBlacklistUser &blacklistedUser :
|
||||||
this->blacklistSetting_.getValue())
|
this->blacklistSetting_.getValue())
|
||||||
{
|
{
|
||||||
this->blacklistedUsers.appendItem(blacklistedUser);
|
this->blacklistedUsers.appendItem(blacklistedUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->blacklistedUsers.delayedItemsChanged.connect([this] {
|
this->blacklistedUsers.delayedItemsChanged.connect([this] {
|
||||||
this->blacklistSetting_.setValue(this->blacklistedUsers.getVector());
|
this->blacklistSetting_.setValue(this->blacklistedUsers.getVector());
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const HighlightPhrase &user : this->userSetting_.getValue())
|
for (const HighlightPhrase &user : this->userSetting_.getValue())
|
||||||
{
|
{
|
||||||
this->highlightedUsers.appendItem(user);
|
this->highlightedUsers.appendItem(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->highlightedUsers.delayedItemsChanged.connect([this] { //
|
this->highlightedUsers.delayedItemsChanged.connect([this] { //
|
||||||
this->userSetting_.setValue(this->highlightedUsers.getVector());
|
this->userSetting_.setValue(this->highlightedUsers.getVector());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
HighlightModel *HighlightController::createModel(QObject *parent)
|
HighlightModel *HighlightController::createModel(QObject *parent)
|
||||||
{
|
{
|
||||||
HighlightModel *model = new HighlightModel(parent);
|
HighlightModel *model = new HighlightModel(parent);
|
||||||
model->init(&this->phrases);
|
model->init(&this->phrases);
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
UserHighlightModel *HighlightController::createUserModel(QObject *parent)
|
UserHighlightModel *HighlightController::createUserModel(QObject *parent)
|
||||||
{
|
{
|
||||||
auto *model = new UserHighlightModel(parent);
|
auto *model = new UserHighlightModel(parent);
|
||||||
model->init(&this->highlightedUsers);
|
model->init(&this->highlightedUsers);
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HighlightController::isHighlightedUser(const QString &username)
|
bool HighlightController::isHighlightedUser(const QString &username)
|
||||||
{
|
{
|
||||||
const auto &userItems = this->highlightedUsers;
|
const auto &userItems = this->highlightedUsers;
|
||||||
for (const auto &highlightedUser : userItems)
|
for (const auto &highlightedUser : userItems)
|
||||||
{
|
{
|
||||||
if (highlightedUser.isMatch(username))
|
if (highlightedUser.isMatch(username))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
HighlightBlacklistModel *HighlightController::createBlacklistModel(
|
HighlightBlacklistModel *HighlightController::createBlacklistModel(
|
||||||
QObject *parent)
|
QObject *parent)
|
||||||
{
|
{
|
||||||
auto *model = new HighlightBlacklistModel(parent);
|
auto *model = new HighlightBlacklistModel(parent);
|
||||||
model->init(&this->blacklistedUsers);
|
model->init(&this->blacklistedUsers);
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HighlightController::blacklistContains(const QString &username)
|
bool HighlightController::blacklistContains(const QString &username)
|
||||||
{
|
{
|
||||||
for (const auto &blacklistedUser : this->blacklistedUsers)
|
for (const auto &blacklistedUser : this->blacklistedUsers)
|
||||||
{
|
{
|
||||||
if (blacklistedUser.isMatch(username))
|
if (blacklistedUser.isMatch(username))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HighlightController::addHighlight(const MessagePtr &msg)
|
void HighlightController::addHighlight(const MessagePtr &msg)
|
||||||
{
|
{
|
||||||
// static NotificationPopup popup;
|
// static NotificationPopup popup;
|
||||||
|
|
||||||
// popup.updatePosition();
|
// popup.updatePosition();
|
||||||
// popup.addMessage(msg);
|
// popup.addMessage(msg);
|
||||||
// popup.show();
|
// popup.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,52 +1,52 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/ChatterinoSetting.hpp"
|
#include "common/ChatterinoSetting.hpp"
|
||||||
#include "common/SignalVector.hpp"
|
#include "common/SignalVector.hpp"
|
||||||
#include "common/Singleton.hpp"
|
#include "common/Singleton.hpp"
|
||||||
#include "controllers/highlights/HighlightBlacklistUser.hpp"
|
#include "controllers/highlights/HighlightBlacklistUser.hpp"
|
||||||
#include "controllers/highlights/HighlightPhrase.hpp"
|
#include "controllers/highlights/HighlightPhrase.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
struct Message;
|
struct Message;
|
||||||
using MessagePtr = std::shared_ptr<const Message>;
|
using MessagePtr = std::shared_ptr<const Message>;
|
||||||
|
|
||||||
class Settings;
|
class Settings;
|
||||||
class Paths;
|
class Paths;
|
||||||
|
|
||||||
class UserHighlightModel;
|
class UserHighlightModel;
|
||||||
class HighlightModel;
|
class HighlightModel;
|
||||||
class HighlightBlacklistModel;
|
class HighlightBlacklistModel;
|
||||||
|
|
||||||
class HighlightController final : public Singleton
|
class HighlightController final : public Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HighlightController();
|
HighlightController();
|
||||||
|
|
||||||
virtual void initialize(Settings &settings, Paths &paths) override;
|
virtual void initialize(Settings &settings, Paths &paths) override;
|
||||||
|
|
||||||
UnsortedSignalVector<HighlightPhrase> phrases;
|
UnsortedSignalVector<HighlightPhrase> phrases;
|
||||||
UnsortedSignalVector<HighlightBlacklistUser> blacklistedUsers;
|
UnsortedSignalVector<HighlightBlacklistUser> blacklistedUsers;
|
||||||
UnsortedSignalVector<HighlightPhrase> highlightedUsers;
|
UnsortedSignalVector<HighlightPhrase> highlightedUsers;
|
||||||
|
|
||||||
HighlightModel *createModel(QObject *parent);
|
HighlightModel *createModel(QObject *parent);
|
||||||
HighlightBlacklistModel *createBlacklistModel(QObject *parent);
|
HighlightBlacklistModel *createBlacklistModel(QObject *parent);
|
||||||
UserHighlightModel *createUserModel(QObject *parent);
|
UserHighlightModel *createUserModel(QObject *parent);
|
||||||
|
|
||||||
bool isHighlightedUser(const QString &username);
|
bool isHighlightedUser(const QString &username);
|
||||||
bool blacklistContains(const QString &username);
|
bool blacklistContains(const QString &username);
|
||||||
|
|
||||||
void addHighlight(const MessagePtr &msg);
|
void addHighlight(const MessagePtr &msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool initialized_ = false;
|
bool initialized_ = false;
|
||||||
|
|
||||||
ChatterinoSetting<std::vector<HighlightPhrase>> highlightsSetting_ = {
|
ChatterinoSetting<std::vector<HighlightPhrase>> highlightsSetting_ = {
|
||||||
"/highlighting/highlights"};
|
"/highlighting/highlights"};
|
||||||
ChatterinoSetting<std::vector<HighlightBlacklistUser>> blacklistSetting_ = {
|
ChatterinoSetting<std::vector<HighlightBlacklistUser>> blacklistSetting_ = {
|
||||||
"/highlighting/blacklist"};
|
"/highlighting/blacklist"};
|
||||||
ChatterinoSetting<std::vector<HighlightPhrase>> userSetting_ = {
|
ChatterinoSetting<std::vector<HighlightPhrase>> userSetting_ = {
|
||||||
"/highlighting/users"};
|
"/highlighting/users"};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,129 +1,131 @@
|
|||||||
#include "HighlightModel.hpp"
|
#include "HighlightModel.hpp"
|
||||||
|
|
||||||
#include "Application.hpp"
|
#include "Application.hpp"
|
||||||
#include "singletons/Settings.hpp"
|
#include "singletons/Settings.hpp"
|
||||||
#include "util/StandardItemHelper.hpp"
|
#include "util/StandardItemHelper.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
// commandmodel
|
// commandmodel
|
||||||
HighlightModel::HighlightModel(QObject *parent)
|
HighlightModel::HighlightModel(QObject *parent)
|
||||||
: SignalVectorModel<HighlightPhrase>(4, parent)
|
: SignalVectorModel<HighlightPhrase>(5, parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// turn a vector item into a model row
|
// turn a vector item into a model row
|
||||||
HighlightPhrase HighlightModel::getItemFromRow(
|
HighlightPhrase HighlightModel::getItemFromRow(
|
||||||
std::vector<QStandardItem *> &row, const HighlightPhrase &original)
|
std::vector<QStandardItem *> &row, const HighlightPhrase &original)
|
||||||
{
|
{
|
||||||
// key, alert, sound, regex
|
// key, alert, sound, regex, case-sensitivity
|
||||||
|
|
||||||
return HighlightPhrase{row[0]->data(Qt::DisplayRole).toString(),
|
return HighlightPhrase{row[0]->data(Qt::DisplayRole).toString(),
|
||||||
row[1]->data(Qt::CheckStateRole).toBool(),
|
row[1]->data(Qt::CheckStateRole).toBool(),
|
||||||
row[2]->data(Qt::CheckStateRole).toBool(),
|
row[2]->data(Qt::CheckStateRole).toBool(),
|
||||||
row[3]->data(Qt::CheckStateRole).toBool()};
|
row[3]->data(Qt::CheckStateRole).toBool(),
|
||||||
}
|
row[4]->data(Qt::CheckStateRole).toBool()};
|
||||||
|
}
|
||||||
// turns a row in the model into a vector item
|
|
||||||
void HighlightModel::getRowFromItem(const HighlightPhrase &item,
|
// turns a row in the model into a vector item
|
||||||
std::vector<QStandardItem *> &row)
|
void HighlightModel::getRowFromItem(const HighlightPhrase &item,
|
||||||
{
|
std::vector<QStandardItem *> &row)
|
||||||
setStringItem(row[0], item.getPattern());
|
{
|
||||||
setBoolItem(row[1], item.getAlert());
|
setStringItem(row[0], item.getPattern());
|
||||||
setBoolItem(row[2], item.getSound());
|
setBoolItem(row[1], item.getAlert());
|
||||||
setBoolItem(row[3], item.isRegex());
|
setBoolItem(row[2], item.getSound());
|
||||||
}
|
setBoolItem(row[3], item.isRegex());
|
||||||
|
setBoolItem(row[4], item.isCaseSensitive());
|
||||||
void HighlightModel::afterInit()
|
}
|
||||||
{
|
|
||||||
std::vector<QStandardItem *> usernameRow = this->createRow();
|
void HighlightModel::afterInit()
|
||||||
setBoolItem(usernameRow[0], getSettings()->enableSelfHighlight.getValue(),
|
{
|
||||||
true, false);
|
std::vector<QStandardItem *> usernameRow = this->createRow();
|
||||||
usernameRow[0]->setData("Your username (automatic)", Qt::DisplayRole);
|
setBoolItem(usernameRow[0], getSettings()->enableSelfHighlight.getValue(),
|
||||||
setBoolItem(usernameRow[1],
|
true, false);
|
||||||
getSettings()->enableSelfHighlightTaskbar.getValue(), true,
|
usernameRow[0]->setData("Your username (automatic)", Qt::DisplayRole);
|
||||||
false);
|
setBoolItem(usernameRow[1],
|
||||||
setBoolItem(usernameRow[2],
|
getSettings()->enableSelfHighlightTaskbar.getValue(), true,
|
||||||
getSettings()->enableSelfHighlightSound.getValue(), true,
|
false);
|
||||||
false);
|
setBoolItem(usernameRow[2],
|
||||||
usernameRow[3]->setFlags(0);
|
getSettings()->enableSelfHighlightSound.getValue(), true,
|
||||||
this->insertCustomRow(usernameRow, 0);
|
false);
|
||||||
std::vector<QStandardItem *> whisperRow = this->createRow();
|
usernameRow[3]->setFlags(0);
|
||||||
setBoolItem(whisperRow[0], getSettings()->enableWhisperHighlight.getValue(),
|
this->insertCustomRow(usernameRow, 0);
|
||||||
true, false);
|
std::vector<QStandardItem *> whisperRow = this->createRow();
|
||||||
whisperRow[0]->setData("Whispers", Qt::DisplayRole);
|
setBoolItem(whisperRow[0], getSettings()->enableWhisperHighlight.getValue(),
|
||||||
setBoolItem(whisperRow[1],
|
true, false);
|
||||||
getSettings()->enableWhisperHighlightTaskbar.getValue(), true,
|
whisperRow[0]->setData("Whispers", Qt::DisplayRole);
|
||||||
false);
|
setBoolItem(whisperRow[1],
|
||||||
setBoolItem(whisperRow[2],
|
getSettings()->enableWhisperHighlightTaskbar.getValue(), true,
|
||||||
getSettings()->enableWhisperHighlightSound.getValue(), true,
|
false);
|
||||||
false);
|
setBoolItem(whisperRow[2],
|
||||||
whisperRow[3]->setFlags(0);
|
getSettings()->enableWhisperHighlightSound.getValue(), true,
|
||||||
this->insertCustomRow(whisperRow, 1);
|
false);
|
||||||
}
|
whisperRow[3]->setFlags(0);
|
||||||
|
this->insertCustomRow(whisperRow, 1);
|
||||||
void HighlightModel::customRowSetData(const std::vector<QStandardItem *> &row,
|
}
|
||||||
int column, const QVariant &value,
|
|
||||||
int role, int rowIndex)
|
void HighlightModel::customRowSetData(const std::vector<QStandardItem *> &row,
|
||||||
{
|
int column, const QVariant &value,
|
||||||
switch (column)
|
int role, int rowIndex)
|
||||||
{
|
{
|
||||||
case 0:
|
switch (column)
|
||||||
{
|
{
|
||||||
if (role == Qt::CheckStateRole)
|
case 0:
|
||||||
{
|
{
|
||||||
if (rowIndex == 0)
|
if (role == Qt::CheckStateRole)
|
||||||
{
|
{
|
||||||
getSettings()->enableSelfHighlight.setValue(value.toBool());
|
if (rowIndex == 0)
|
||||||
}
|
{
|
||||||
else if (rowIndex == 1)
|
getSettings()->enableSelfHighlight.setValue(value.toBool());
|
||||||
{
|
}
|
||||||
getSettings()->enableWhisperHighlight.setValue(
|
else if (rowIndex == 1)
|
||||||
value.toBool());
|
{
|
||||||
}
|
getSettings()->enableWhisperHighlight.setValue(
|
||||||
}
|
value.toBool());
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case 1:
|
}
|
||||||
{
|
break;
|
||||||
if (role == Qt::CheckStateRole)
|
case 1:
|
||||||
{
|
{
|
||||||
if (rowIndex == 0)
|
if (role == Qt::CheckStateRole)
|
||||||
{
|
{
|
||||||
getSettings()->enableSelfHighlightTaskbar.setValue(
|
if (rowIndex == 0)
|
||||||
value.toBool());
|
{
|
||||||
}
|
getSettings()->enableSelfHighlightTaskbar.setValue(
|
||||||
else if (rowIndex == 1)
|
value.toBool());
|
||||||
{
|
}
|
||||||
getSettings()->enableWhisperHighlightTaskbar.setValue(
|
else if (rowIndex == 1)
|
||||||
value.toBool());
|
{
|
||||||
}
|
getSettings()->enableWhisperHighlightTaskbar.setValue(
|
||||||
}
|
value.toBool());
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case 2:
|
}
|
||||||
{
|
break;
|
||||||
if (role == Qt::CheckStateRole)
|
case 2:
|
||||||
{
|
{
|
||||||
if (rowIndex == 0)
|
if (role == Qt::CheckStateRole)
|
||||||
{
|
{
|
||||||
getSettings()->enableSelfHighlightSound.setValue(
|
if (rowIndex == 0)
|
||||||
value.toBool());
|
{
|
||||||
}
|
getSettings()->enableSelfHighlightSound.setValue(
|
||||||
else if (rowIndex == 1)
|
value.toBool());
|
||||||
{
|
}
|
||||||
getSettings()->enableWhisperHighlightSound.setValue(
|
else if (rowIndex == 1)
|
||||||
value.toBool());
|
{
|
||||||
}
|
getSettings()->enableWhisperHighlightSound.setValue(
|
||||||
}
|
value.toBool());
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case 3:
|
}
|
||||||
{
|
break;
|
||||||
// empty element
|
case 3:
|
||||||
}
|
{
|
||||||
break;
|
// empty element
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
} // namespace chatterino
|
}
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "common/SignalVectorModel.hpp"
|
#include "common/SignalVectorModel.hpp"
|
||||||
#include "controllers/highlights/HighlightPhrase.hpp"
|
#include "controllers/highlights/HighlightPhrase.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class HighlightController;
|
class HighlightController;
|
||||||
|
|
||||||
class HighlightModel : public SignalVectorModel<HighlightPhrase>
|
class HighlightModel : public SignalVectorModel<HighlightPhrase>
|
||||||
{
|
{
|
||||||
explicit HighlightModel(QObject *parent);
|
explicit HighlightModel(QObject *parent);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// turn a vector item into a model row
|
// turn a vector item into a model row
|
||||||
virtual HighlightPhrase getItemFromRow(
|
virtual HighlightPhrase getItemFromRow(
|
||||||
std::vector<QStandardItem *> &row,
|
std::vector<QStandardItem *> &row,
|
||||||
const HighlightPhrase &original) override;
|
const HighlightPhrase &original) override;
|
||||||
|
|
||||||
// turns a row in the model into a vector item
|
// turns a row in the model into a vector item
|
||||||
virtual void getRowFromItem(const HighlightPhrase &item,
|
virtual void getRowFromItem(const HighlightPhrase &item,
|
||||||
std::vector<QStandardItem *> &row) override;
|
std::vector<QStandardItem *> &row) override;
|
||||||
|
|
||||||
virtual void afterInit() override;
|
virtual void afterInit() override;
|
||||||
|
|
||||||
virtual void customRowSetData(const std::vector<QStandardItem *> &row,
|
virtual void customRowSetData(const std::vector<QStandardItem *> &row,
|
||||||
int column, const QVariant &value, int role,
|
int column, const QVariant &value, int role,
|
||||||
int rowIndex) override;
|
int rowIndex) override;
|
||||||
|
|
||||||
friend class HighlightController;
|
friend class HighlightController;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,113 +1,127 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "util/RapidJsonSerializeQString.hpp"
|
#include "util/RapidJsonSerializeQString.hpp"
|
||||||
#include "util/RapidjsonHelpers.hpp"
|
#include "util/RapidjsonHelpers.hpp"
|
||||||
|
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <pajlada/serialize.hpp>
|
#include <pajlada/serialize.hpp>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class HighlightPhrase
|
class HighlightPhrase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool operator==(const HighlightPhrase &other) const
|
bool operator==(const HighlightPhrase &other) const
|
||||||
{
|
{
|
||||||
return std::tie(this->pattern_, this->sound_, this->alert_,
|
return std::tie(this->pattern_, this->sound_, this->alert_,
|
||||||
this->isRegex_) == std::tie(other.pattern_,
|
this->isRegex_, this->caseSensitive_) ==
|
||||||
other.sound_, other.alert_,
|
std::tie(other.pattern_, other.sound_, other.alert_,
|
||||||
other.isRegex_);
|
other.isRegex_, other.caseSensitive_);
|
||||||
}
|
}
|
||||||
|
|
||||||
HighlightPhrase(const QString &pattern, bool alert, bool sound,
|
HighlightPhrase(const QString &pattern, bool alert, bool sound,
|
||||||
bool isRegex)
|
bool isRegex, bool caseSensitive)
|
||||||
: pattern_(pattern)
|
: pattern_(pattern)
|
||||||
, alert_(alert)
|
, alert_(alert)
|
||||||
, sound_(sound)
|
, sound_(sound)
|
||||||
, isRegex_(isRegex)
|
, isRegex_(isRegex)
|
||||||
, regex_(isRegex_ ? pattern
|
, caseSensitive_(caseSensitive)
|
||||||
: "\\b" + QRegularExpression::escape(pattern) + "\\b",
|
, regex_(
|
||||||
QRegularExpression::CaseInsensitiveOption |
|
isRegex_ ? pattern
|
||||||
QRegularExpression::UseUnicodePropertiesOption)
|
: "\\b" + QRegularExpression::escape(pattern) + "\\b",
|
||||||
{
|
QRegularExpression::UseUnicodePropertiesOption |
|
||||||
}
|
(caseSensitive_ ? QRegularExpression::NoPatternOption
|
||||||
|
: QRegularExpression::CaseInsensitiveOption))
|
||||||
const QString &getPattern() const
|
{
|
||||||
{
|
}
|
||||||
return this->pattern_;
|
|
||||||
}
|
const QString &getPattern() const
|
||||||
bool getAlert() const
|
{
|
||||||
{
|
return this->pattern_;
|
||||||
return this->alert_;
|
}
|
||||||
}
|
bool getAlert() const
|
||||||
bool getSound() const
|
{
|
||||||
{
|
return this->alert_;
|
||||||
return this->sound_;
|
}
|
||||||
}
|
bool getSound() const
|
||||||
bool isRegex() const
|
{
|
||||||
{
|
return this->sound_;
|
||||||
return this->isRegex_;
|
}
|
||||||
}
|
bool isRegex() const
|
||||||
|
{
|
||||||
bool isValid() const
|
return this->isRegex_;
|
||||||
{
|
}
|
||||||
return !this->pattern_.isEmpty() && this->regex_.isValid();
|
|
||||||
}
|
bool isValid() const
|
||||||
|
{
|
||||||
bool isMatch(const QString &subject) const
|
return !this->pattern_.isEmpty() && this->regex_.isValid();
|
||||||
{
|
}
|
||||||
return this->isValid() && this->regex_.match(subject).hasMatch();
|
|
||||||
}
|
bool isMatch(const QString &subject) const
|
||||||
|
{
|
||||||
private:
|
return this->isValid() && this->regex_.match(subject).hasMatch();
|
||||||
QString pattern_;
|
}
|
||||||
bool alert_;
|
|
||||||
bool sound_;
|
bool isCaseSensitive() const
|
||||||
bool isRegex_;
|
{
|
||||||
QRegularExpression regex_;
|
return this->caseSensitive_;
|
||||||
};
|
}
|
||||||
} // namespace chatterino
|
|
||||||
|
private:
|
||||||
namespace pajlada {
|
QString pattern_;
|
||||||
|
bool alert_;
|
||||||
template <>
|
bool sound_;
|
||||||
struct Serialize<chatterino::HighlightPhrase> {
|
bool isRegex_;
|
||||||
static rapidjson::Value get(const chatterino::HighlightPhrase &value,
|
bool caseSensitive_;
|
||||||
rapidjson::Document::AllocatorType &a)
|
QRegularExpression regex_;
|
||||||
{
|
};
|
||||||
rapidjson::Value ret(rapidjson::kObjectType);
|
} // namespace chatterino
|
||||||
|
|
||||||
chatterino::rj::set(ret, "pattern", value.getPattern(), a);
|
namespace pajlada {
|
||||||
chatterino::rj::set(ret, "alert", value.getAlert(), a);
|
|
||||||
chatterino::rj::set(ret, "sound", value.getSound(), a);
|
template <>
|
||||||
chatterino::rj::set(ret, "regex", value.isRegex(), a);
|
struct Serialize<chatterino::HighlightPhrase> {
|
||||||
|
static rapidjson::Value get(const chatterino::HighlightPhrase &value,
|
||||||
return ret;
|
rapidjson::Document::AllocatorType &a)
|
||||||
}
|
{
|
||||||
};
|
rapidjson::Value ret(rapidjson::kObjectType);
|
||||||
|
|
||||||
template <>
|
chatterino::rj::set(ret, "pattern", value.getPattern(), a);
|
||||||
struct Deserialize<chatterino::HighlightPhrase> {
|
chatterino::rj::set(ret, "alert", value.getAlert(), a);
|
||||||
static chatterino::HighlightPhrase get(const rapidjson::Value &value)
|
chatterino::rj::set(ret, "sound", value.getSound(), a);
|
||||||
{
|
chatterino::rj::set(ret, "regex", value.isRegex(), a);
|
||||||
if (!value.IsObject())
|
chatterino::rj::set(ret, "case", value.isCaseSensitive(), a);
|
||||||
{
|
|
||||||
return chatterino::HighlightPhrase(QString(), true, false, false);
|
return ret;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
QString _pattern;
|
|
||||||
bool _alert = true;
|
template <>
|
||||||
bool _sound = false;
|
struct Deserialize<chatterino::HighlightPhrase> {
|
||||||
bool _isRegex = false;
|
static chatterino::HighlightPhrase get(const rapidjson::Value &value)
|
||||||
|
{
|
||||||
chatterino::rj::getSafe(value, "pattern", _pattern);
|
if (!value.IsObject())
|
||||||
chatterino::rj::getSafe(value, "alert", _alert);
|
{
|
||||||
chatterino::rj::getSafe(value, "sound", _sound);
|
return chatterino::HighlightPhrase(QString(), true, false, false,
|
||||||
chatterino::rj::getSafe(value, "regex", _isRegex);
|
false);
|
||||||
|
}
|
||||||
return chatterino::HighlightPhrase(_pattern, _alert, _sound, _isRegex);
|
|
||||||
}
|
QString _pattern;
|
||||||
};
|
bool _alert = true;
|
||||||
|
bool _sound = false;
|
||||||
} // namespace pajlada
|
bool _isRegex = false;
|
||||||
|
bool _caseSensitive = false;
|
||||||
|
|
||||||
|
chatterino::rj::getSafe(value, "pattern", _pattern);
|
||||||
|
chatterino::rj::getSafe(value, "alert", _alert);
|
||||||
|
chatterino::rj::getSafe(value, "sound", _sound);
|
||||||
|
chatterino::rj::getSafe(value, "regex", _isRegex);
|
||||||
|
chatterino::rj::getSafe(value, "case", _caseSensitive);
|
||||||
|
|
||||||
|
return chatterino::HighlightPhrase(_pattern, _alert, _sound,
|
||||||
|
_isRegex, _caseSensitive);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace pajlada
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace chatterino {
|
|||||||
|
|
||||||
// commandmodel
|
// commandmodel
|
||||||
UserHighlightModel::UserHighlightModel(QObject *parent)
|
UserHighlightModel::UserHighlightModel(QObject *parent)
|
||||||
: SignalVectorModel<HighlightPhrase>(4, parent)
|
: SignalVectorModel<HighlightPhrase>(5, parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,7 +21,8 @@ HighlightPhrase UserHighlightModel::getItemFromRow(
|
|||||||
return HighlightPhrase{row[0]->data(Qt::DisplayRole).toString(),
|
return HighlightPhrase{row[0]->data(Qt::DisplayRole).toString(),
|
||||||
row[1]->data(Qt::CheckStateRole).toBool(),
|
row[1]->data(Qt::CheckStateRole).toBool(),
|
||||||
row[2]->data(Qt::CheckStateRole).toBool(),
|
row[2]->data(Qt::CheckStateRole).toBool(),
|
||||||
row[3]->data(Qt::CheckStateRole).toBool()};
|
row[3]->data(Qt::CheckStateRole).toBool(),
|
||||||
|
row[4]->data(Qt::CheckStateRole).toBool()};
|
||||||
}
|
}
|
||||||
|
|
||||||
// row into vector item
|
// row into vector item
|
||||||
@@ -32,6 +33,7 @@ void UserHighlightModel::getRowFromItem(const HighlightPhrase &item,
|
|||||||
setBoolItem(row[1], item.getAlert());
|
setBoolItem(row[1], item.getAlert());
|
||||||
setBoolItem(row[2], item.getSound());
|
setBoolItem(row[2], item.getSound());
|
||||||
setBoolItem(row[3], item.isRegex());
|
setBoolItem(row[3], item.isRegex());
|
||||||
|
setBoolItem(row[4], item.isCaseSensitive());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,121 +1,121 @@
|
|||||||
#include "ModerationAction.hpp"
|
#include "ModerationAction.hpp"
|
||||||
|
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include "Application.hpp"
|
#include "Application.hpp"
|
||||||
#include "messages/Image.hpp"
|
#include "messages/Image.hpp"
|
||||||
#include "singletons/Resources.hpp"
|
#include "singletons/Resources.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
// ModerationAction::ModerationAction(Image *_image, const QString &_action)
|
// ModerationAction::ModerationAction(Image *_image, const QString &_action)
|
||||||
// : _isImage(true)
|
// : _isImage(true)
|
||||||
// , image(_image)
|
// , image(_image)
|
||||||
// , action(_action)
|
// , action(_action)
|
||||||
//{
|
//{
|
||||||
//}
|
//}
|
||||||
|
|
||||||
// ModerationAction::ModerationAction(const QString &_line1, const QString
|
// ModerationAction::ModerationAction(const QString &_line1, const QString
|
||||||
// &_line2,
|
// &_line2,
|
||||||
// const QString &_action)
|
// const QString &_action)
|
||||||
// : _isImage(false)
|
// : _isImage(false)
|
||||||
// , image(nullptr)
|
// , image(nullptr)
|
||||||
// , line1(_line1)
|
// , line1(_line1)
|
||||||
// , line2(_line2)
|
// , line2(_line2)
|
||||||
// , action(_action)
|
// , action(_action)
|
||||||
//{
|
//{
|
||||||
//}
|
//}
|
||||||
|
|
||||||
ModerationAction::ModerationAction(const QString &action)
|
ModerationAction::ModerationAction(const QString &action)
|
||||||
: action_(action)
|
: action_(action)
|
||||||
{
|
{
|
||||||
static QRegularExpression replaceRegex("[!/.]");
|
static QRegularExpression replaceRegex("[!/.]");
|
||||||
static QRegularExpression timeoutRegex("^[./]timeout.* (\\d+)");
|
static QRegularExpression timeoutRegex("^[./]timeout.* (\\d+)");
|
||||||
|
|
||||||
auto timeoutMatch = timeoutRegex.match(action);
|
auto timeoutMatch = timeoutRegex.match(action);
|
||||||
|
|
||||||
if (timeoutMatch.hasMatch())
|
if (timeoutMatch.hasMatch())
|
||||||
{
|
{
|
||||||
// if (multipleTimeouts > 1) {
|
// if (multipleTimeouts > 1) {
|
||||||
// QString line1;
|
// QString line1;
|
||||||
// QString line2;
|
// QString line2;
|
||||||
|
|
||||||
int amount = timeoutMatch.captured(1).toInt();
|
int amount = timeoutMatch.captured(1).toInt();
|
||||||
|
|
||||||
if (amount < 60)
|
if (amount < 60)
|
||||||
{
|
{
|
||||||
this->line1_ = QString::number(amount);
|
this->line1_ = QString::number(amount);
|
||||||
this->line2_ = "s";
|
this->line2_ = "s";
|
||||||
}
|
}
|
||||||
else if (amount < 60 * 60)
|
else if (amount < 60 * 60)
|
||||||
{
|
{
|
||||||
this->line1_ = QString::number(amount / 60);
|
this->line1_ = QString::number(amount / 60);
|
||||||
this->line2_ = "m";
|
this->line2_ = "m";
|
||||||
}
|
}
|
||||||
else if (amount < 60 * 60 * 24)
|
else if (amount < 60 * 60 * 24)
|
||||||
{
|
{
|
||||||
this->line1_ = QString::number(amount / 60 / 60);
|
this->line1_ = QString::number(amount / 60 / 60);
|
||||||
this->line2_ = "h";
|
this->line2_ = "h";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->line1_ = QString::number(amount / 60 / 60 / 24);
|
this->line1_ = QString::number(amount / 60 / 60 / 24);
|
||||||
this->line2_ = "d";
|
this->line2_ = "d";
|
||||||
}
|
}
|
||||||
|
|
||||||
// line1 = this->line1_;
|
// line1 = this->line1_;
|
||||||
// line2 = this->line2_;
|
// line2 = this->line2_;
|
||||||
// } else {
|
// } else {
|
||||||
// this->_moderationActions.emplace_back(app->resources->buttonTimeout,
|
// this->_moderationActions.emplace_back(app->resources->buttonTimeout,
|
||||||
// str);
|
// str);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
else if (action.startsWith("/ban "))
|
else if (action.startsWith("/ban "))
|
||||||
{
|
{
|
||||||
this->image_ = Image::fromPixmap(getApp()->resources->buttons.ban);
|
this->image_ = Image::fromPixmap(getApp()->resources->buttons.ban);
|
||||||
}
|
}
|
||||||
else if (action.startsWith("/delete "))
|
else if (action.startsWith("/delete "))
|
||||||
{
|
{
|
||||||
this->image_ = Image::fromPixmap(getApp()->resources->buttons.trashCan);
|
this->image_ = Image::fromPixmap(getApp()->resources->buttons.trashCan);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QString xD = action;
|
QString xD = action;
|
||||||
|
|
||||||
xD.replace(replaceRegex, "");
|
xD.replace(replaceRegex, "");
|
||||||
|
|
||||||
this->line1_ = xD.mid(0, 2);
|
this->line1_ = xD.mid(0, 2);
|
||||||
this->line2_ = xD.mid(2, 2);
|
this->line2_ = xD.mid(2, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModerationAction::operator==(const ModerationAction &other) const
|
bool ModerationAction::operator==(const ModerationAction &other) const
|
||||||
{
|
{
|
||||||
return this == std::addressof(other);
|
return this == std::addressof(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModerationAction::isImage() const
|
bool ModerationAction::isImage() const
|
||||||
{
|
{
|
||||||
return bool(this->image_);
|
return bool(this->image_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const boost::optional<ImagePtr> &ModerationAction::getImage() const
|
const boost::optional<ImagePtr> &ModerationAction::getImage() const
|
||||||
{
|
{
|
||||||
return this->image_;
|
return this->image_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString &ModerationAction::getLine1() const
|
const QString &ModerationAction::getLine1() const
|
||||||
{
|
{
|
||||||
return this->line1_;
|
return this->line1_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString &ModerationAction::getLine2() const
|
const QString &ModerationAction::getLine2() const
|
||||||
{
|
{
|
||||||
return this->line2_;
|
return this->line2_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString &ModerationAction::getAction() const
|
const QString &ModerationAction::getAction() const
|
||||||
{
|
{
|
||||||
return this->action_;
|
return this->action_;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,68 +1,68 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <pajlada/serialize.hpp>
|
#include <pajlada/serialize.hpp>
|
||||||
|
|
||||||
#include "util/RapidjsonHelpers.hpp"
|
#include "util/RapidjsonHelpers.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class Image;
|
class Image;
|
||||||
using ImagePtr = std::shared_ptr<Image>;
|
using ImagePtr = std::shared_ptr<Image>;
|
||||||
|
|
||||||
class ModerationAction
|
class ModerationAction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ModerationAction(const QString &action);
|
ModerationAction(const QString &action);
|
||||||
|
|
||||||
bool operator==(const ModerationAction &other) const;
|
bool operator==(const ModerationAction &other) const;
|
||||||
|
|
||||||
bool isImage() const;
|
bool isImage() const;
|
||||||
const boost::optional<ImagePtr> &getImage() const;
|
const boost::optional<ImagePtr> &getImage() const;
|
||||||
const QString &getLine1() const;
|
const QString &getLine1() const;
|
||||||
const QString &getLine2() const;
|
const QString &getLine2() const;
|
||||||
const QString &getAction() const;
|
const QString &getAction() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::optional<ImagePtr> image_;
|
boost::optional<ImagePtr> image_;
|
||||||
QString line1_;
|
QString line1_;
|
||||||
QString line2_;
|
QString line2_;
|
||||||
QString action_;
|
QString action_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
||||||
namespace pajlada {
|
namespace pajlada {
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct Serialize<chatterino::ModerationAction> {
|
struct Serialize<chatterino::ModerationAction> {
|
||||||
static rapidjson::Value get(const chatterino::ModerationAction &value,
|
static rapidjson::Value get(const chatterino::ModerationAction &value,
|
||||||
rapidjson::Document::AllocatorType &a)
|
rapidjson::Document::AllocatorType &a)
|
||||||
{
|
{
|
||||||
rapidjson::Value ret(rapidjson::kObjectType);
|
rapidjson::Value ret(rapidjson::kObjectType);
|
||||||
|
|
||||||
chatterino::rj::set(ret, "pattern", value.getAction(), a);
|
chatterino::rj::set(ret, "pattern", value.getAction(), a);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct Deserialize<chatterino::ModerationAction> {
|
struct Deserialize<chatterino::ModerationAction> {
|
||||||
static chatterino::ModerationAction get(const rapidjson::Value &value)
|
static chatterino::ModerationAction get(const rapidjson::Value &value)
|
||||||
{
|
{
|
||||||
if (!value.IsObject())
|
if (!value.IsObject())
|
||||||
{
|
{
|
||||||
return chatterino::ModerationAction(QString());
|
return chatterino::ModerationAction(QString());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString pattern;
|
QString pattern;
|
||||||
|
|
||||||
chatterino::rj::getSafe(value, "pattern", pattern);
|
chatterino::rj::getSafe(value, "pattern", pattern);
|
||||||
|
|
||||||
return chatterino::ModerationAction(pattern);
|
return chatterino::ModerationAction(pattern);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pajlada
|
} // namespace pajlada
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
#include "ModerationActionModel.hpp"
|
#include "ModerationActionModel.hpp"
|
||||||
|
|
||||||
#include "util/StandardItemHelper.hpp"
|
#include "util/StandardItemHelper.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
// commandmodel
|
// commandmodel
|
||||||
ModerationActionModel ::ModerationActionModel(QObject *parent)
|
ModerationActionModel ::ModerationActionModel(QObject *parent)
|
||||||
: SignalVectorModel<ModerationAction>(1, parent)
|
: SignalVectorModel<ModerationAction>(1, parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// turn a vector item into a model row
|
// turn a vector item into a model row
|
||||||
ModerationAction ModerationActionModel::getItemFromRow(
|
ModerationAction ModerationActionModel::getItemFromRow(
|
||||||
std::vector<QStandardItem *> &row, const ModerationAction &original)
|
std::vector<QStandardItem *> &row, const ModerationAction &original)
|
||||||
{
|
{
|
||||||
return ModerationAction(row[0]->data(Qt::DisplayRole).toString());
|
return ModerationAction(row[0]->data(Qt::DisplayRole).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// turns a row in the model into a vector item
|
// turns a row in the model into a vector item
|
||||||
void ModerationActionModel::getRowFromItem(const ModerationAction &item,
|
void ModerationActionModel::getRowFromItem(const ModerationAction &item,
|
||||||
std::vector<QStandardItem *> &row)
|
std::vector<QStandardItem *> &row)
|
||||||
{
|
{
|
||||||
setStringItem(row[0], item.getAction());
|
setStringItem(row[0], item.getAction());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "common/SignalVectorModel.hpp"
|
#include "common/SignalVectorModel.hpp"
|
||||||
#include "controllers/moderationactions/ModerationAction.hpp"
|
#include "controllers/moderationactions/ModerationAction.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class ModerationActions;
|
class ModerationActions;
|
||||||
|
|
||||||
class ModerationActionModel : public SignalVectorModel<ModerationAction>
|
class ModerationActionModel : public SignalVectorModel<ModerationAction>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ModerationActionModel(QObject *parent);
|
explicit ModerationActionModel(QObject *parent);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// turn a vector item into a model row
|
// turn a vector item into a model row
|
||||||
virtual ModerationAction getItemFromRow(
|
virtual ModerationAction getItemFromRow(
|
||||||
std::vector<QStandardItem *> &row,
|
std::vector<QStandardItem *> &row,
|
||||||
const ModerationAction &original) override;
|
const ModerationAction &original) override;
|
||||||
|
|
||||||
// turns a row in the model into a vector item
|
// turns a row in the model into a vector item
|
||||||
virtual void getRowFromItem(const ModerationAction &item,
|
virtual void getRowFromItem(const ModerationAction &item,
|
||||||
std::vector<QStandardItem *> &row) override;
|
std::vector<QStandardItem *> &row) override;
|
||||||
|
|
||||||
friend class HighlightController;
|
friend class HighlightController;
|
||||||
|
|
||||||
friend class ModerationActions;
|
friend class ModerationActions;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,42 +1,42 @@
|
|||||||
#include "ModerationActions.hpp"
|
#include "ModerationActions.hpp"
|
||||||
|
|
||||||
#include "Application.hpp"
|
#include "Application.hpp"
|
||||||
#include "controllers/moderationactions/ModerationActionModel.hpp"
|
#include "controllers/moderationactions/ModerationActionModel.hpp"
|
||||||
#include "singletons/Settings.hpp"
|
#include "singletons/Settings.hpp"
|
||||||
|
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
ModerationActions::ModerationActions()
|
ModerationActions::ModerationActions()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModerationActions::initialize(Settings &settings, Paths &paths)
|
void ModerationActions::initialize(Settings &settings, Paths &paths)
|
||||||
{
|
{
|
||||||
assert(!this->initialized_);
|
assert(!this->initialized_);
|
||||||
this->initialized_ = true;
|
this->initialized_ = true;
|
||||||
|
|
||||||
this->setting_ =
|
this->setting_ =
|
||||||
std::make_unique<ChatterinoSetting<std::vector<ModerationAction>>>(
|
std::make_unique<ChatterinoSetting<std::vector<ModerationAction>>>(
|
||||||
"/moderation/actions");
|
"/moderation/actions");
|
||||||
|
|
||||||
for (auto &val : this->setting_->getValue())
|
for (auto &val : this->setting_->getValue())
|
||||||
{
|
{
|
||||||
this->items.insertItem(val);
|
this->items.insertItem(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->items.delayedItemsChanged.connect([this] { //
|
this->items.delayedItemsChanged.connect([this] { //
|
||||||
this->setting_->setValue(this->items.getVector());
|
this->setting_->setValue(this->items.getVector());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ModerationActionModel *ModerationActions::createModel(QObject *parent)
|
ModerationActionModel *ModerationActions::createModel(QObject *parent)
|
||||||
{
|
{
|
||||||
ModerationActionModel *model = new ModerationActionModel(parent);
|
ModerationActionModel *model = new ModerationActionModel(parent);
|
||||||
model->init(&this->items);
|
model->init(&this->items);
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/Singleton.hpp"
|
#include "common/Singleton.hpp"
|
||||||
|
|
||||||
#include "common/ChatterinoSetting.hpp"
|
#include "common/ChatterinoSetting.hpp"
|
||||||
#include "common/SignalVector.hpp"
|
#include "common/SignalVector.hpp"
|
||||||
#include "controllers/moderationactions/ModerationAction.hpp"
|
#include "controllers/moderationactions/ModerationAction.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class Settings;
|
class Settings;
|
||||||
class Paths;
|
class Paths;
|
||||||
|
|
||||||
class ModerationActionModel;
|
class ModerationActionModel;
|
||||||
|
|
||||||
class ModerationActions final : public Singleton
|
class ModerationActions final : public Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ModerationActions();
|
ModerationActions();
|
||||||
|
|
||||||
virtual void initialize(Settings &settings, Paths &paths) override;
|
virtual void initialize(Settings &settings, Paths &paths) override;
|
||||||
|
|
||||||
UnsortedSignalVector<ModerationAction> items;
|
UnsortedSignalVector<ModerationAction> items;
|
||||||
|
|
||||||
ModerationActionModel *createModel(QObject *parent);
|
ModerationActionModel *createModel(QObject *parent);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<ChatterinoSetting<std::vector<ModerationAction>>> setting_;
|
std::unique_ptr<ChatterinoSetting<std::vector<ModerationAction>>> setting_;
|
||||||
bool initialized_ = false;
|
bool initialized_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,36 +1,36 @@
|
|||||||
#include "TaggedUser.hpp"
|
#include "TaggedUser.hpp"
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
TaggedUser::TaggedUser(ProviderId provider, const QString &name,
|
TaggedUser::TaggedUser(ProviderId provider, const QString &name,
|
||||||
const QString &id)
|
const QString &id)
|
||||||
: providerId_(provider)
|
: providerId_(provider)
|
||||||
, name_(name)
|
, name_(name)
|
||||||
, id_(id)
|
, id_(id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TaggedUser::operator<(const TaggedUser &other) const
|
bool TaggedUser::operator<(const TaggedUser &other) const
|
||||||
{
|
{
|
||||||
return std::tie(this->providerId_, this->name_, this->id_) <
|
return std::tie(this->providerId_, this->name_, this->id_) <
|
||||||
std::tie(other.providerId_, other.name_, other.id_);
|
std::tie(other.providerId_, other.name_, other.id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProviderId TaggedUser::getProviderId() const
|
ProviderId TaggedUser::getProviderId() const
|
||||||
{
|
{
|
||||||
return this->providerId_;
|
return this->providerId_;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TaggedUser::getName() const
|
QString TaggedUser::getName() const
|
||||||
{
|
{
|
||||||
return this->name_;
|
return this->name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TaggedUser::getId() const
|
QString TaggedUser::getId() const
|
||||||
{
|
{
|
||||||
return this->id_;
|
return this->id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/ProviderId.hpp"
|
#include "common/ProviderId.hpp"
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class TaggedUser
|
class TaggedUser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TaggedUser(ProviderId providerId, const QString &name, const QString &id);
|
TaggedUser(ProviderId providerId, const QString &name, const QString &id);
|
||||||
|
|
||||||
bool operator<(const TaggedUser &other) const;
|
bool operator<(const TaggedUser &other) const;
|
||||||
|
|
||||||
ProviderId getProviderId() const;
|
ProviderId getProviderId() const;
|
||||||
QString getName() const;
|
QString getName() const;
|
||||||
QString getId() const;
|
QString getId() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProviderId providerId_;
|
ProviderId providerId_;
|
||||||
QString name_;
|
QString name_;
|
||||||
QString id_;
|
QString id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
#include "TaggedUsersController.hpp"
|
#include "TaggedUsersController.hpp"
|
||||||
|
|
||||||
#include "controllers/taggedusers/TaggedUsersModel.hpp"
|
#include "controllers/taggedusers/TaggedUsersModel.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
TaggedUsersController::TaggedUsersController()
|
TaggedUsersController::TaggedUsersController()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TaggedUsersModel *TaggedUsersController::createModel(QObject *parent)
|
TaggedUsersModel *TaggedUsersController::createModel(QObject *parent)
|
||||||
{
|
{
|
||||||
TaggedUsersModel *model = new TaggedUsersModel(parent);
|
TaggedUsersModel *model = new TaggedUsersModel(parent);
|
||||||
model->init(&this->users);
|
model->init(&this->users);
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/Singleton.hpp"
|
#include "common/Singleton.hpp"
|
||||||
|
|
||||||
#include "common/SignalVector.hpp"
|
#include "common/SignalVector.hpp"
|
||||||
#include "controllers/taggedusers/TaggedUser.hpp"
|
#include "controllers/taggedusers/TaggedUser.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class TaggedUsersModel;
|
class TaggedUsersModel;
|
||||||
|
|
||||||
class TaggedUsersController final : public Singleton
|
class TaggedUsersController final : public Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TaggedUsersController();
|
TaggedUsersController();
|
||||||
|
|
||||||
SortedSignalVector<TaggedUser, std::less<TaggedUser>> users;
|
SortedSignalVector<TaggedUser, std::less<TaggedUser>> users;
|
||||||
|
|
||||||
TaggedUsersModel *createModel(QObject *parent = nullptr);
|
TaggedUsersModel *createModel(QObject *parent = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,67 +1,67 @@
|
|||||||
#include "TaggedUsersModel.hpp"
|
#include "TaggedUsersModel.hpp"
|
||||||
|
|
||||||
#include "Application.hpp"
|
#include "Application.hpp"
|
||||||
#include "util/StandardItemHelper.hpp"
|
#include "util/StandardItemHelper.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
// commandmodel
|
// commandmodel
|
||||||
TaggedUsersModel::TaggedUsersModel(QObject *parent)
|
TaggedUsersModel::TaggedUsersModel(QObject *parent)
|
||||||
: SignalVectorModel<TaggedUser>(1, parent)
|
: SignalVectorModel<TaggedUser>(1, parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// turn a vector item into a model row
|
// turn a vector item into a model row
|
||||||
TaggedUser TaggedUsersModel::getItemFromRow(std::vector<QStandardItem *> &row,
|
TaggedUser TaggedUsersModel::getItemFromRow(std::vector<QStandardItem *> &row,
|
||||||
const TaggedUser &original)
|
const TaggedUser &original)
|
||||||
{
|
{
|
||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
|
|
||||||
// turns a row in the model into a vector item
|
// turns a row in the model into a vector item
|
||||||
void TaggedUsersModel::getRowFromItem(const TaggedUser &item,
|
void TaggedUsersModel::getRowFromItem(const TaggedUser &item,
|
||||||
std::vector<QStandardItem *> &row)
|
std::vector<QStandardItem *> &row)
|
||||||
{
|
{
|
||||||
setStringItem(row[0], item.getName());
|
setStringItem(row[0], item.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaggedUsersModel::afterInit()
|
void TaggedUsersModel::afterInit()
|
||||||
{
|
{
|
||||||
// std::vector<QStandardItem *> row = this->createRow();
|
// std::vector<QStandardItem *> row = this->createRow();
|
||||||
// setBoolItem(row[0],
|
// setBoolItem(row[0],
|
||||||
// getSettings()->enableHighlightsSelf.getValue(), true, false);
|
// getSettings()->enableHighlightsSelf.getValue(), true, false);
|
||||||
// row[0]->setData("Your username (automatic)", Qt::DisplayRole);
|
// row[0]->setData("Your username (automatic)", Qt::DisplayRole);
|
||||||
// setBoolItem(row[1],
|
// setBoolItem(row[1],
|
||||||
// getSettings()->enableHighlightTaskbar.getValue(), true, false);
|
// getSettings()->enableHighlightTaskbar.getValue(), true, false);
|
||||||
// setBoolItem(row[2],
|
// setBoolItem(row[2],
|
||||||
// getSettings()->enableHighlightSound.getValue(), true, false);
|
// getSettings()->enableHighlightSound.getValue(), true, false);
|
||||||
// row[3]->setFlags(0); this->insertCustomRow(row, 0);
|
// row[3]->setFlags(0); this->insertCustomRow(row, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// void TaggedUserModel::customRowSetData(const std::vector<QStandardItem *>
|
// void TaggedUserModel::customRowSetData(const std::vector<QStandardItem *>
|
||||||
// &row, int column,
|
// &row, int column,
|
||||||
// const QVariant &value, int role)
|
// const QVariant &value, int role)
|
||||||
//{
|
//{
|
||||||
// switch (column) {
|
// switch (column) {
|
||||||
// case 0: {
|
// case 0: {
|
||||||
// if (role == Qt::CheckStateRole) {
|
// if (role == Qt::CheckStateRole) {
|
||||||
// getSettings()->enableHighlightsSelf.setValue(value.toBool());
|
// getSettings()->enableHighlightsSelf.setValue(value.toBool());
|
||||||
// }
|
// }
|
||||||
// } break;
|
// } break;
|
||||||
// case 1: {
|
// case 1: {
|
||||||
// if (role == Qt::CheckStateRole) {
|
// if (role == Qt::CheckStateRole) {
|
||||||
// getSettings()->enableHighlightTaskbar.setValue(value.toBool());
|
// getSettings()->enableHighlightTaskbar.setValue(value.toBool());
|
||||||
// }
|
// }
|
||||||
// } break;
|
// } break;
|
||||||
// case 2: {
|
// case 2: {
|
||||||
// if (role == Qt::CheckStateRole) {
|
// if (role == Qt::CheckStateRole) {
|
||||||
// getSettings()->enableHighlightSound.setValue(value.toBool());
|
// getSettings()->enableHighlightSound.setValue(value.toBool());
|
||||||
// }
|
// }
|
||||||
// } break;
|
// } break;
|
||||||
// case 3: {
|
// case 3: {
|
||||||
// // empty element
|
// // empty element
|
||||||
// } break;
|
// } break;
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/SignalVectorModel.hpp"
|
#include "common/SignalVectorModel.hpp"
|
||||||
#include "controllers/taggedusers/TaggedUser.hpp"
|
#include "controllers/taggedusers/TaggedUser.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class TaggedUsersController;
|
class TaggedUsersController;
|
||||||
|
|
||||||
class TaggedUsersModel : public SignalVectorModel<TaggedUser>
|
class TaggedUsersModel : public SignalVectorModel<TaggedUser>
|
||||||
{
|
{
|
||||||
explicit TaggedUsersModel(QObject *parent);
|
explicit TaggedUsersModel(QObject *parent);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// turn a vector item into a model row
|
// turn a vector item into a model row
|
||||||
virtual TaggedUser getItemFromRow(std::vector<QStandardItem *> &row,
|
virtual TaggedUser getItemFromRow(std::vector<QStandardItem *> &row,
|
||||||
const TaggedUser &original) override;
|
const TaggedUser &original) override;
|
||||||
|
|
||||||
// turns a row in the model into a vector item
|
// turns a row in the model into a vector item
|
||||||
virtual void getRowFromItem(const TaggedUser &item,
|
virtual void getRowFromItem(const TaggedUser &item,
|
||||||
std::vector<QStandardItem *> &row) override;
|
std::vector<QStandardItem *> &row) override;
|
||||||
|
|
||||||
virtual void afterInit() override;
|
virtual void afterInit() override;
|
||||||
|
|
||||||
// virtual void customRowSetData(const std::vector<QStandardItem *> &row,
|
// virtual void customRowSetData(const std::vector<QStandardItem *> &row,
|
||||||
// int column,
|
// int column,
|
||||||
// const QVariant &value, int role)
|
// const QVariant &value, int role)
|
||||||
// override;
|
// override;
|
||||||
|
|
||||||
friend class TaggedUsersController;
|
friend class TaggedUsersController;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t size()
|
std::size_t size() const
|
||||||
{
|
{
|
||||||
return this->length_;
|
return this->length_;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#include "MessageContainer.hpp"
|
#include "MessageContainer.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
MessageContainer::MessageContainer()
|
MessageContainer::MessageContainer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class MessageContainer
|
class MessageContainer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MessageContainer();
|
MessageContainer();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ void EmoteElement::addToContainer(MessageLayoutContainer &container,
|
|||||||
QSize(int(container.getScale() * image->width() * emoteScale),
|
QSize(int(container.getScale() * image->width() * emoteScale),
|
||||||
int(container.getScale() * image->height() * emoteScale));
|
int(container.getScale() * image->height() * emoteScale));
|
||||||
|
|
||||||
container.addElement((new ImageLayoutElement(*this, image, size))
|
container.addElement(this->makeImageLayoutElement(image, size)
|
||||||
->setLink(this->getLink()));
|
->setLink(this->getLink()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -159,6 +159,27 @@ void EmoteElement::addToContainer(MessageLayoutContainer &container,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MessageLayoutElement *EmoteElement::makeImageLayoutElement(
|
||||||
|
const ImagePtr &image, const QSize &size)
|
||||||
|
{
|
||||||
|
return new ImageLayoutElement(*this, image, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MOD BADGE
|
||||||
|
ModBadgeElement::ModBadgeElement(const EmotePtr &data,
|
||||||
|
MessageElementFlags flags_)
|
||||||
|
: EmoteElement(data, flags_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageLayoutElement *ModBadgeElement::makeImageLayoutElement(
|
||||||
|
const ImagePtr &image, const QSize &size)
|
||||||
|
{
|
||||||
|
static const QColor modBadgeBackgroundColor("#34AE0A");
|
||||||
|
return new ImageWithBackgroundLayoutElement(*this, image, size,
|
||||||
|
modBadgeBackgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
// BADGE
|
// BADGE
|
||||||
BadgeElement::BadgeElement(const EmotePtr &emote, MessageElementFlags flags)
|
BadgeElement::BadgeElement(const EmotePtr &emote, MessageElementFlags flags)
|
||||||
: MessageElement(flags)
|
: MessageElement(flags)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
class Channel;
|
class Channel;
|
||||||
struct MessageLayoutContainer;
|
struct MessageLayoutContainer;
|
||||||
|
class MessageLayoutElement;
|
||||||
|
|
||||||
class Image;
|
class Image;
|
||||||
using ImagePtr = std::shared_ptr<Image>;
|
using ImagePtr = std::shared_ptr<Image>;
|
||||||
@@ -209,11 +210,26 @@ public:
|
|||||||
MessageElementFlags flags_) override;
|
MessageElementFlags flags_) override;
|
||||||
EmotePtr getEmote() const;
|
EmotePtr getEmote() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual MessageLayoutElement *makeImageLayoutElement(const ImagePtr &image,
|
||||||
|
const QSize &size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<TextElement> textElement_;
|
std::unique_ptr<TextElement> textElement_;
|
||||||
EmotePtr emote_;
|
EmotePtr emote_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Behaves like an emote element, except it creates a different image layout element that draws the mod badge background
|
||||||
|
class ModBadgeElement : public EmoteElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ModBadgeElement(const EmotePtr &data, MessageElementFlags flags_);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MessageLayoutElement *makeImageLayoutElement(const ImagePtr &image,
|
||||||
|
const QSize &size) override;
|
||||||
|
};
|
||||||
|
|
||||||
class BadgeElement : public MessageElement
|
class BadgeElement : public MessageElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
+90
-90
@@ -1,90 +1,90 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
struct SelectionItem {
|
struct SelectionItem {
|
||||||
int messageIndex;
|
int messageIndex;
|
||||||
int charIndex;
|
int charIndex;
|
||||||
|
|
||||||
SelectionItem()
|
SelectionItem()
|
||||||
{
|
{
|
||||||
this->messageIndex = 0;
|
this->messageIndex = 0;
|
||||||
this->charIndex = 0;
|
this->charIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectionItem(int _messageIndex, int _charIndex)
|
SelectionItem(int _messageIndex, int _charIndex)
|
||||||
{
|
{
|
||||||
this->messageIndex = _messageIndex;
|
this->messageIndex = _messageIndex;
|
||||||
|
|
||||||
this->charIndex = _charIndex;
|
this->charIndex = _charIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(const SelectionItem &b) const
|
bool operator<(const SelectionItem &b) const
|
||||||
{
|
{
|
||||||
return std::tie(this->messageIndex, this->charIndex) <
|
return std::tie(this->messageIndex, this->charIndex) <
|
||||||
std::tie(b.messageIndex, b.charIndex);
|
std::tie(b.messageIndex, b.charIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator>(const SelectionItem &b) const
|
bool operator>(const SelectionItem &b) const
|
||||||
{
|
{
|
||||||
return !this->operator==(b) && b.operator<(*this);
|
return !this->operator==(b) && b.operator<(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const SelectionItem &b) const
|
bool operator==(const SelectionItem &b) const
|
||||||
{
|
{
|
||||||
return this->messageIndex == b.messageIndex &&
|
return this->messageIndex == b.messageIndex &&
|
||||||
this->charIndex == b.charIndex;
|
this->charIndex == b.charIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const SelectionItem &b) const
|
bool operator!=(const SelectionItem &b) const
|
||||||
{
|
{
|
||||||
return this->operator==(b);
|
return this->operator==(b);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Selection {
|
struct Selection {
|
||||||
SelectionItem start;
|
SelectionItem start;
|
||||||
SelectionItem end;
|
SelectionItem end;
|
||||||
SelectionItem selectionMin;
|
SelectionItem selectionMin;
|
||||||
SelectionItem selectionMax;
|
SelectionItem selectionMax;
|
||||||
|
|
||||||
Selection() = default;
|
Selection() = default;
|
||||||
|
|
||||||
Selection(const SelectionItem &start, const SelectionItem &end)
|
Selection(const SelectionItem &start, const SelectionItem &end)
|
||||||
: start(start)
|
: start(start)
|
||||||
, end(end)
|
, end(end)
|
||||||
, selectionMin(start)
|
, selectionMin(start)
|
||||||
, selectionMax(end)
|
, selectionMax(end)
|
||||||
{
|
{
|
||||||
if (selectionMin > selectionMax)
|
if (selectionMin > selectionMax)
|
||||||
{
|
{
|
||||||
std::swap(this->selectionMin, this->selectionMax);
|
std::swap(this->selectionMin, this->selectionMax);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isEmpty() const
|
bool isEmpty() const
|
||||||
{
|
{
|
||||||
return this->start == this->end;
|
return this->start == this->end;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSingleMessage() const
|
bool isSingleMessage() const
|
||||||
{
|
{
|
||||||
return this->selectionMin.messageIndex ==
|
return this->selectionMin.messageIndex ==
|
||||||
this->selectionMax.messageIndex;
|
this->selectionMax.messageIndex;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DoubleClickSelection {
|
struct DoubleClickSelection {
|
||||||
int originalStart = 0;
|
int originalStart = 0;
|
||||||
int originalEnd = 0;
|
int originalEnd = 0;
|
||||||
int origMessageIndex;
|
int origMessageIndex;
|
||||||
bool selectingLeft = false;
|
bool selectingLeft = false;
|
||||||
bool selectingRight = false;
|
bool selectingRight = false;
|
||||||
SelectionItem origStartItem;
|
SelectionItem origStartItem;
|
||||||
SelectionItem origEndItem;
|
SelectionItem origEndItem;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,117 +1,117 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QPoint>
|
#include <QPoint>
|
||||||
#include <QRect>
|
#include <QRect>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "common/Common.hpp"
|
#include "common/Common.hpp"
|
||||||
#include "common/FlagsEnum.hpp"
|
#include "common/FlagsEnum.hpp"
|
||||||
#include "messages/Selection.hpp"
|
#include "messages/Selection.hpp"
|
||||||
#include "messages/layouts/MessageLayoutElement.hpp"
|
#include "messages/layouts/MessageLayoutElement.hpp"
|
||||||
|
|
||||||
class QPainter;
|
class QPainter;
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
enum class MessageFlag : uint32_t;
|
enum class MessageFlag : uint32_t;
|
||||||
using MessageFlags = FlagsEnum<MessageFlag>;
|
using MessageFlags = FlagsEnum<MessageFlag>;
|
||||||
|
|
||||||
struct Margin {
|
struct Margin {
|
||||||
int top;
|
int top;
|
||||||
int right;
|
int right;
|
||||||
int bottom;
|
int bottom;
|
||||||
int left;
|
int left;
|
||||||
|
|
||||||
Margin()
|
Margin()
|
||||||
: Margin(0)
|
: Margin(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Margin(int value)
|
Margin(int value)
|
||||||
: Margin(value, value, value, value)
|
: Margin(value, value, value, value)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Margin(int _top, int _right, int _bottom, int _left)
|
Margin(int _top, int _right, int _bottom, int _left)
|
||||||
: top(_top)
|
: top(_top)
|
||||||
, right(_right)
|
, right(_right)
|
||||||
, bottom(_bottom)
|
, bottom(_bottom)
|
||||||
, left(_left)
|
, left(_left)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MessageLayoutContainer {
|
struct MessageLayoutContainer {
|
||||||
MessageLayoutContainer() = default;
|
MessageLayoutContainer() = default;
|
||||||
|
|
||||||
Margin margin = {4, 8, 4, 8};
|
Margin margin = {4, 8, 4, 8};
|
||||||
bool centered = false;
|
bool centered = false;
|
||||||
bool enableCompactEmotes = false;
|
bool enableCompactEmotes = false;
|
||||||
|
|
||||||
int getHeight() const;
|
int getHeight() const;
|
||||||
int getWidth() const;
|
int getWidth() const;
|
||||||
float getScale() const;
|
float getScale() const;
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
void begin(int width_, float scale_, MessageFlags flags_);
|
void begin(int width_, float scale_, MessageFlags flags_);
|
||||||
void end();
|
void end();
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
bool canAddElements();
|
bool canAddElements();
|
||||||
void addElement(MessageLayoutElement *element);
|
void addElement(MessageLayoutElement *element);
|
||||||
void addElementNoLineBreak(MessageLayoutElement *element);
|
void addElementNoLineBreak(MessageLayoutElement *element);
|
||||||
void breakLine();
|
void breakLine();
|
||||||
bool atStartOfLine();
|
bool atStartOfLine();
|
||||||
bool fitsInLine(int width_);
|
bool fitsInLine(int width_);
|
||||||
MessageLayoutElement *getElementAt(QPoint point);
|
MessageLayoutElement *getElementAt(QPoint point);
|
||||||
|
|
||||||
// painting
|
// painting
|
||||||
void paintElements(QPainter &painter);
|
void paintElements(QPainter &painter);
|
||||||
void paintAnimatedElements(QPainter &painter, int yOffset);
|
void paintAnimatedElements(QPainter &painter, int yOffset);
|
||||||
void paintSelection(QPainter &painter, int messageIndex,
|
void paintSelection(QPainter &painter, int messageIndex,
|
||||||
Selection &selection, int yOffset);
|
Selection &selection, int yOffset);
|
||||||
|
|
||||||
// selection
|
// selection
|
||||||
int getSelectionIndex(QPoint point);
|
int getSelectionIndex(QPoint point);
|
||||||
int getLastCharacterIndex() const;
|
int getLastCharacterIndex() const;
|
||||||
int getFirstMessageCharacterIndex() const;
|
int getFirstMessageCharacterIndex() const;
|
||||||
void addSelectionText(QString &str, int from, int to, CopyMode copymode);
|
void addSelectionText(QString &str, int from, int to, CopyMode copymode);
|
||||||
|
|
||||||
bool isCollapsed();
|
bool isCollapsed();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Line {
|
struct Line {
|
||||||
int startIndex;
|
int startIndex;
|
||||||
int endIndex;
|
int endIndex;
|
||||||
int startCharIndex;
|
int startCharIndex;
|
||||||
int endCharIndex;
|
int endCharIndex;
|
||||||
QRect rect;
|
QRect rect;
|
||||||
};
|
};
|
||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
void _addElement(MessageLayoutElement *element, bool forceAdd = false);
|
void _addElement(MessageLayoutElement *element, bool forceAdd = false);
|
||||||
bool canCollapse();
|
bool canCollapse();
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
float scale_ = 1.f;
|
float scale_ = 1.f;
|
||||||
int width_ = 0;
|
int width_ = 0;
|
||||||
MessageFlags flags_{};
|
MessageFlags flags_{};
|
||||||
int line_ = 0;
|
int line_ = 0;
|
||||||
int height_ = 0;
|
int height_ = 0;
|
||||||
int currentX_ = 0;
|
int currentX_ = 0;
|
||||||
int currentY_ = 0;
|
int currentY_ = 0;
|
||||||
int charIndex_ = 0;
|
int charIndex_ = 0;
|
||||||
size_t lineStart_ = 0;
|
size_t lineStart_ = 0;
|
||||||
int lineHeight_ = 0;
|
int lineHeight_ = 0;
|
||||||
int spaceWidth_ = 4;
|
int spaceWidth_ = 4;
|
||||||
int textLineHeight_ = 0;
|
int textLineHeight_ = 0;
|
||||||
int dotdotdotWidth_ = 0;
|
int dotdotdotWidth_ = 0;
|
||||||
bool canAddMessages_ = true;
|
bool canAddMessages_ = true;
|
||||||
bool isCollapsed_ = false;
|
bool isCollapsed_ = false;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<MessageLayoutElement>> elements_;
|
std::vector<std::unique_ptr<MessageLayoutElement>> elements_;
|
||||||
std::vector<Line> lines_;
|
std::vector<Line> lines_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -168,6 +168,33 @@ int ImageLayoutElement::getXFromIndex(int index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// IMAGE WITH BACKGROUND
|
||||||
|
//
|
||||||
|
ImageWithBackgroundLayoutElement::ImageWithBackgroundLayoutElement(
|
||||||
|
MessageElement &creator, ImagePtr image, const QSize &size, QColor color)
|
||||||
|
: ImageLayoutElement(creator, image, size)
|
||||||
|
, color_(color)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageWithBackgroundLayoutElement::paint(QPainter &painter)
|
||||||
|
{
|
||||||
|
if (this->image_ == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pixmap = this->image_->pixmapOrLoad();
|
||||||
|
if (pixmap && !this->image_->animated())
|
||||||
|
{
|
||||||
|
painter.fillRect(QRectF(this->getRect()), this->color_);
|
||||||
|
|
||||||
|
// fourtf: make it use qreal values
|
||||||
|
painter.drawPixmap(QRectF(this->getRect()), *pixmap, QRectF());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// TEXT
|
// TEXT
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -72,10 +72,22 @@ protected:
|
|||||||
int getMouseOverIndex(const QPoint &abs) const override;
|
int getMouseOverIndex(const QPoint &abs) const override;
|
||||||
int getXFromIndex(int index) override;
|
int getXFromIndex(int index) override;
|
||||||
|
|
||||||
private:
|
|
||||||
ImagePtr image_;
|
ImagePtr image_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ImageWithBackgroundLayoutElement : public ImageLayoutElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ImageWithBackgroundLayoutElement(MessageElement &creator, ImagePtr image,
|
||||||
|
const QSize &size, QColor color);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paint(QPainter &painter) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QColor color_;
|
||||||
|
};
|
||||||
|
|
||||||
// TEXT
|
// TEXT
|
||||||
class TextLayoutElement : public MessageLayoutElement
|
class TextLayoutElement : public MessageLayoutElement
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#include "messages/search/AuthorPredicate.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
AuthorPredicate::AuthorPredicate(const QStringList &authors)
|
||||||
|
: authors_()
|
||||||
|
{
|
||||||
|
// Check if any comma-seperated values were passed and transform those
|
||||||
|
for (const auto &entry : authors)
|
||||||
|
{
|
||||||
|
for (const auto &author : entry.split(',', QString::SkipEmptyParts))
|
||||||
|
{
|
||||||
|
this->authors_ << author;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AuthorPredicate::appliesTo(const Message &message)
|
||||||
|
{
|
||||||
|
return authors_.contains(message.displayName, Qt::CaseInsensitive) ||
|
||||||
|
authors_.contains(message.loginName, Qt::CaseInsensitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "messages/search/MessagePredicate.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief MessagePredicate checking for the author/sender of a message.
|
||||||
|
*
|
||||||
|
* This predicate will only allow messages that are sent by a list of users,
|
||||||
|
* specified by their user names.
|
||||||
|
*/
|
||||||
|
class AuthorPredicate : public MessagePredicate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Create an AuthorPredicate with a list of users to search for.
|
||||||
|
*
|
||||||
|
* @param authors a list of user names that a message should be sent from
|
||||||
|
*/
|
||||||
|
AuthorPredicate(const QStringList &authors);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks whether the message is authored by any of the users passed
|
||||||
|
* in the constructor.
|
||||||
|
*
|
||||||
|
* @param message the message to check
|
||||||
|
* @return true if the message was authored by one of the specified users,
|
||||||
|
* false otherwise
|
||||||
|
*/
|
||||||
|
bool appliesTo(const Message &message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Holds the user names that will be searched for
|
||||||
|
QStringList authors_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#include "messages/search/LinkPredicate.hpp"
|
||||||
|
#include "common/LinkParser.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
LinkPredicate::LinkPredicate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LinkPredicate::appliesTo(const Message &message)
|
||||||
|
{
|
||||||
|
for (const auto &word :
|
||||||
|
message.messageText.split(' ', QString::SkipEmptyParts))
|
||||||
|
{
|
||||||
|
if (LinkParser(word).hasMatch())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "messages/search/MessagePredicate.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief MessagePredicate checking whether a link exists in the message.
|
||||||
|
*
|
||||||
|
* This predicate will only allow messages that contain a link.
|
||||||
|
*/
|
||||||
|
class LinkPredicate : public MessagePredicate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LinkPredicate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks whether the message contains a link.
|
||||||
|
*
|
||||||
|
* @param message the message to check
|
||||||
|
* @return true if the message contains a link, false otherwise
|
||||||
|
*/
|
||||||
|
bool appliesTo(const Message &message);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "messages/Message.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Abstract base class for message predicates.
|
||||||
|
*
|
||||||
|
* Message predicates define certain features a message can satisfy.
|
||||||
|
* Features are represented by classes derived from this abstract class.
|
||||||
|
* A derived class must override `appliesTo` in order to test for the desired
|
||||||
|
* feature.
|
||||||
|
*/
|
||||||
|
class MessagePredicate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Checks whether this predicate applies to the passed message.
|
||||||
|
*
|
||||||
|
* Implementations of `appliesTo` should never change the message's content
|
||||||
|
* in order to be compatible with other MessagePredicates.
|
||||||
|
*
|
||||||
|
* @param message the message to check for this predicate
|
||||||
|
* @return true if this predicate applies, false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool appliesTo(const Message &message) = 0;
|
||||||
|
};
|
||||||
|
} // namespace chatterino
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#include "messages/search/SubstringPredicate.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
SubstringPredicate::SubstringPredicate(const QString &search)
|
||||||
|
: search_(search)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SubstringPredicate::appliesTo(const Message &message)
|
||||||
|
{
|
||||||
|
return message.searchText.contains(this->search_, Qt::CaseInsensitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "messages/search/MessagePredicate.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief MessagePredicate checking whether a substring exists in the message.
|
||||||
|
*
|
||||||
|
* This predicate will only allow messages that contain a certain substring in
|
||||||
|
* their `searchText`.
|
||||||
|
*/
|
||||||
|
class SubstringPredicate : public MessagePredicate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Create a SubstringPredicate with a substring to search for.
|
||||||
|
*
|
||||||
|
* The passed string is searched for case-insensitively.
|
||||||
|
*
|
||||||
|
* @param search the string to search for in the message
|
||||||
|
*/
|
||||||
|
SubstringPredicate(const QString &search);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks whether the message contains the substring passed in the
|
||||||
|
* constructor.
|
||||||
|
*
|
||||||
|
* The check is done case-insensitively.
|
||||||
|
*
|
||||||
|
* @param message the message to check
|
||||||
|
* @return true if the message contains the substring, false otherwise
|
||||||
|
*/
|
||||||
|
bool appliesTo(const Message &message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Holds the substring to search for in a message's `messageText`
|
||||||
|
const QString search_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
+59
-59
@@ -1,59 +1,59 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class NullablePtr
|
class NullablePtr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NullablePtr()
|
NullablePtr()
|
||||||
: element_(nullptr)
|
: element_(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NullablePtr(T *element)
|
NullablePtr(T *element)
|
||||||
: element_(element)
|
: element_(element)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
T *operator->() const
|
T *operator->() const
|
||||||
{
|
{
|
||||||
assert(this->hasElement());
|
assert(this->hasElement());
|
||||||
|
|
||||||
return element_;
|
return element_;
|
||||||
}
|
}
|
||||||
|
|
||||||
T &operator*() const
|
T &operator*() const
|
||||||
{
|
{
|
||||||
assert(this->hasElement());
|
assert(this->hasElement());
|
||||||
|
|
||||||
return *element_;
|
return *element_;
|
||||||
}
|
}
|
||||||
|
|
||||||
T *get() const
|
T *get() const
|
||||||
{
|
{
|
||||||
assert(this->hasElement());
|
assert(this->hasElement());
|
||||||
|
|
||||||
return this->element_;
|
return this->element_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNull() const
|
bool isNull() const
|
||||||
{
|
{
|
||||||
return this->element_ == nullptr;
|
return this->element_ == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasElement() const
|
bool hasElement() const
|
||||||
{
|
{
|
||||||
return this->element_ != nullptr;
|
return this->element_ != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator bool() const
|
operator bool() const
|
||||||
{
|
{
|
||||||
return this->hasElement();
|
return this->hasElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T *element_;
|
T *element_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -79,7 +79,38 @@ namespace {
|
|||||||
|
|
||||||
return {Success, std::move(emotes)};
|
return {Success, std::move(emotes)};
|
||||||
}
|
}
|
||||||
std::pair<Outcome, EmoteMap> parseChannelEmotes(const QJsonObject &jsonRoot)
|
|
||||||
|
boost::optional<EmotePtr> parseModBadge(const QJsonObject &jsonRoot)
|
||||||
|
{
|
||||||
|
boost::optional<EmotePtr> modBadge;
|
||||||
|
|
||||||
|
auto room = jsonRoot.value("room").toObject();
|
||||||
|
auto modUrls = room.value("mod_urls").toObject();
|
||||||
|
if (!modUrls.isEmpty())
|
||||||
|
{
|
||||||
|
auto modBadge1x = getEmoteLink(modUrls, "1");
|
||||||
|
auto modBadge2x = getEmoteLink(modUrls, "2");
|
||||||
|
auto modBadge3x = getEmoteLink(modUrls, "4");
|
||||||
|
|
||||||
|
auto modBadgeImageSet = ImageSet{
|
||||||
|
Image::fromUrl(modBadge1x, 1),
|
||||||
|
modBadge2x.string.isEmpty() ? Image::getEmpty()
|
||||||
|
: Image::fromUrl(modBadge2x, 0.5),
|
||||||
|
modBadge3x.string.isEmpty() ? Image::getEmpty()
|
||||||
|
: Image::fromUrl(modBadge3x, 0.25),
|
||||||
|
};
|
||||||
|
|
||||||
|
modBadge = std::make_shared<Emote>(Emote{
|
||||||
|
{""},
|
||||||
|
modBadgeImageSet,
|
||||||
|
Tooltip{"Twitch Channel Moderator"},
|
||||||
|
modBadge1x,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return modBadge;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmoteMap parseChannelEmotes(const QJsonObject &jsonRoot)
|
||||||
{
|
{
|
||||||
auto jsonSets = jsonRoot.value("sets").toObject();
|
auto jsonSets = jsonRoot.value("sets").toObject();
|
||||||
auto emotes = EmoteMap();
|
auto emotes = EmoteMap();
|
||||||
@@ -110,7 +141,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {Success, std::move(emotes)};
|
return emotes;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@@ -151,19 +182,26 @@ void FfzEmotes::loadEmotes()
|
|||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FfzEmotes::loadChannel(const QString &channelId,
|
void FfzEmotes::loadChannel(
|
||||||
std::function<void(EmoteMap &&)> callback)
|
const QString &channelId, std::function<void(EmoteMap &&)> emoteCallback,
|
||||||
|
std::function<void(boost::optional<EmotePtr>)> modBadgeCallback)
|
||||||
{
|
{
|
||||||
log("[FFZEmotes] Reload FFZ Channel Emotes for channel {}\n", channelId);
|
log("[FFZEmotes] Reload FFZ Channel Emotes for channel {}\n", channelId);
|
||||||
|
|
||||||
NetworkRequest("https://api.frankerfacez.com/v1/room/id/" + channelId)
|
NetworkRequest("https://api.frankerfacez.com/v1/room/id/" + channelId)
|
||||||
|
|
||||||
.timeout(20000)
|
.timeout(20000)
|
||||||
.onSuccess([callback = std::move(callback)](auto result) -> Outcome {
|
.onSuccess([emoteCallback = std::move(emoteCallback),
|
||||||
auto pair = parseChannelEmotes(result.parseJson());
|
modBadgeCallback =
|
||||||
if (pair.first)
|
std::move(modBadgeCallback)](auto result) -> Outcome {
|
||||||
callback(std::move(pair.second));
|
auto json = result.parseJson();
|
||||||
return pair.first;
|
auto emoteMap = parseChannelEmotes(json);
|
||||||
|
auto modBadge = parseModBadge(json);
|
||||||
|
|
||||||
|
emoteCallback(std::move(emoteMap));
|
||||||
|
modBadgeCallback(std::move(modBadge));
|
||||||
|
|
||||||
|
return Success;
|
||||||
})
|
})
|
||||||
.onError([channelId](int result) {
|
.onError([channelId](int result) {
|
||||||
if (result == 203)
|
if (result == 203)
|
||||||
|
|||||||
@@ -22,8 +22,10 @@ public:
|
|||||||
std::shared_ptr<const EmoteMap> emotes() const;
|
std::shared_ptr<const EmoteMap> emotes() const;
|
||||||
boost::optional<EmotePtr> emote(const EmoteName &name) const;
|
boost::optional<EmotePtr> emote(const EmoteName &name) const;
|
||||||
void loadEmotes();
|
void loadEmotes();
|
||||||
static void loadChannel(const QString &channelId,
|
static void loadChannel(
|
||||||
std::function<void(EmoteMap &&)> callback);
|
const QString &channelId,
|
||||||
|
std::function<void(EmoteMap &&)> emoteCallback,
|
||||||
|
std::function<void(boost::optional<EmotePtr>)> modBadgeCallback);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Atomic<std::shared_ptr<const EmoteMap>> global_;
|
Atomic<std::shared_ptr<const EmoteMap>> global_;
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
#include "FfzModBadge.hpp"
|
|
||||||
|
|
||||||
#include <QBuffer>
|
|
||||||
#include <QImageReader>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
#include "common/NetworkRequest.hpp"
|
|
||||||
#include "common/Outcome.hpp"
|
|
||||||
#include "messages/Emote.hpp"
|
|
||||||
|
|
||||||
namespace chatterino {
|
|
||||||
|
|
||||||
FfzModBadge::FfzModBadge(const QString &channelName)
|
|
||||||
: channelName_(channelName)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void FfzModBadge::loadCustomModBadge()
|
|
||||||
{
|
|
||||||
static QString partialUrl("https://cdn.frankerfacez.com/room-badge/mod/");
|
|
||||||
|
|
||||||
QString url = partialUrl + channelName_ + "/1";
|
|
||||||
NetworkRequest(url)
|
|
||||||
|
|
||||||
.onSuccess([this, url](auto result) -> Outcome {
|
|
||||||
auto data = result.getData();
|
|
||||||
|
|
||||||
QBuffer buffer(const_cast<QByteArray *>(&data));
|
|
||||||
buffer.open(QIODevice::ReadOnly);
|
|
||||||
QImageReader reader(&buffer);
|
|
||||||
if (reader.imageCount() == 0)
|
|
||||||
return Failure;
|
|
||||||
|
|
||||||
QPixmap badgeOverlay = QPixmap::fromImageReader(&reader);
|
|
||||||
QPixmap badgePixmap(18, 18);
|
|
||||||
|
|
||||||
// the default mod badge green color
|
|
||||||
badgePixmap.fill(QColor("#34AE0A"));
|
|
||||||
QPainter painter(&badgePixmap);
|
|
||||||
QRectF rect(0, 0, 18, 18);
|
|
||||||
painter.drawPixmap(rect, badgeOverlay, rect);
|
|
||||||
|
|
||||||
auto emote = Emote{{""},
|
|
||||||
ImageSet{Image::fromPixmap(badgePixmap)},
|
|
||||||
Tooltip{"Twitch Channel Moderator"},
|
|
||||||
Url{url}};
|
|
||||||
|
|
||||||
this->badge_ = std::make_shared<Emote>(emote);
|
|
||||||
// getBadge.execute();
|
|
||||||
|
|
||||||
return Success;
|
|
||||||
})
|
|
||||||
.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
EmotePtr FfzModBadge::badge() const
|
|
||||||
{
|
|
||||||
return this->badge_;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace chatterino
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user