connect and heartbeat

This commit is contained in:
ouwou 2020-08-17 02:40:03 -04:00
parent 212511e29d
commit 18af78e6af
14 changed files with 653 additions and 0 deletions

64
.clang-format Normal file
View File

@ -0,0 +1,64 @@
---
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveDeclarations: 'false'
AlignOperands: 'true'
AlignTrailingComments: 'true'
AllowAllArgumentsOnNextLine: 'false'
AllowAllConstructorInitializersOnNextLine: 'false'
AllowAllParametersOfDeclarationOnNextLine: 'false'
AllowShortBlocksOnASingleLine: 'true'
AllowShortCaseLabelsOnASingleLine: 'true'
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: Always
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: 'true'
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: 'false'
AlwaysBreakTemplateDeclarations: 'Yes'
BinPackArguments: 'true'
BinPackParameters: 'true'
BreakAfterJavaFieldAnnotations: 'true'
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: 'true'
BreakConstructorInitializers: BeforeComma
BreakInheritanceList: BeforeComma
BreakStringLiterals: 'true'
ColumnLimit: '0'
CompactNamespaces: 'false'
ConstructorInitializerAllOnOneLineOrOnePerLine: 'false'
ContinuationIndentWidth: '4'
Cpp11BracedListStyle: 'false'
DerivePointerAlignment: 'false'
FixNamespaceComments: 'true'
IncludeBlocks: Merge
IndentCaseLabels: 'true'
IndentPPDirectives: BeforeHash
IndentWidth: '4'
IndentWrappedFunctionNames: 'false'
JavaScriptQuotes: Double
KeepEmptyLinesAtTheStartOfBlocks: 'false'
Language: Cpp
NamespaceIndentation: Inner
PointerAlignment: Right
SortIncludes: 'false'
SpaceAfterCStyleCast: 'false'
SpaceAfterLogicalNot: 'false'
SpaceAfterTemplateKeyword: 'false'
SpaceBeforeAssignmentOperators: 'true'
SpaceBeforeCpp11BracedList: 'true'
SpaceBeforeCtorInitializerColon: 'true'
SpaceBeforeInheritanceColon: 'true'
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: 'true'
SpaceInEmptyParentheses: 'false'
SpacesInAngles: 'false'
SpacesInCStyleCastParentheses: 'false'
SpacesInParentheses: 'false'
SpacesInSquareBrackets: 'false'
Standard: Auto
TabWidth: '4'
...

31
Abaddon.sln Normal file
View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30204.135
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Abaddon", "Abaddon.vcxproj", "{A2A67504-F7F1-4DD3-B86B-68033416FFF5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A2A67504-F7F1-4DD3-B86B-68033416FFF5}.Debug|x64.ActiveCfg = Debug|x64
{A2A67504-F7F1-4DD3-B86B-68033416FFF5}.Debug|x64.Build.0 = Debug|x64
{A2A67504-F7F1-4DD3-B86B-68033416FFF5}.Debug|x86.ActiveCfg = Debug|Win32
{A2A67504-F7F1-4DD3-B86B-68033416FFF5}.Debug|x86.Build.0 = Debug|Win32
{A2A67504-F7F1-4DD3-B86B-68033416FFF5}.Release|x64.ActiveCfg = Release|x64
{A2A67504-F7F1-4DD3-B86B-68033416FFF5}.Release|x64.Build.0 = Release|x64
{A2A67504-F7F1-4DD3-B86B-68033416FFF5}.Release|x86.ActiveCfg = Release|Win32
{A2A67504-F7F1-4DD3-B86B-68033416FFF5}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CA30A7C6-E05A-4D4C-BC71-1D4C80E5647E}
EndGlobalSection
EndGlobal

160
Abaddon.vcxproj Normal file
View File

@ -0,0 +1,160 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{a2a67504-f7f1-4dd3-b86b-68033416fff5}</ProjectGuid>
<RootNamespace>Abaddon</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="abaddon.cpp" />
<ClCompile Include="components\channels.cpp" />
<ClCompile Include="discord\discord.cpp" />
<ClCompile Include="discord\websocket.cpp" />
<ClCompile Include="windows\mainwindow.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="components\channels.hpp" />
<ClInclude Include="abaddon.hpp" />
<ClInclude Include="discord\discord.hpp" />
<ClInclude Include="discord\websocket.hpp" />
<ClInclude Include="windows\mainwindow.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

51
Abaddon.vcxproj.filters Normal file
View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="abaddon.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="windows\mainwindow.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="components\channels.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="discord\websocket.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="discord\discord.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="windows\mainwindow.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="components\channels.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="discord\discord.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="discord\websocket.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="abaddon.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

44
abaddon.cpp Normal file
View File

@ -0,0 +1,44 @@
#include <gtkmm.h>
#include "discord/discord.hpp"
#include "windows/mainwindow.hpp"
#include <memory>
#include "abaddon.hpp"
#ifdef _WIN32
#pragma comment(lib, "crypt32.lib")
#endif
int Abaddon::DoMainLoop() {
m_gtk_app = Gtk::Application::create("com.github.lorpus.abaddon");
MainWindow main;
main.SetAbaddon(this);
main.set_title("Abaddon");
main.show();
m_gtk_app->signal_shutdown().connect([&]() {
m_discord.Stop();
});
/*sigc::connection draw_signal_handler = main.signal_draw().connect([&](const Cairo::RefPtr<Cairo::Context> &ctx) -> bool {
draw_signal_handler.disconnect();
return false;
});*/
return m_gtk_app->run(main);
}
void Abaddon::StartDiscordThread() {
m_discord.Start();
}
void Abaddon::ActionConnect() {
if (!m_discord.IsStarted())
StartDiscordThread();
}
int main(int argc, char **argv) {
Abaddon abaddon;
return abaddon.DoMainLoop();
}

14
abaddon.hpp Normal file
View File

@ -0,0 +1,14 @@
#include <gtkmm.h>
#include "discord/discord.hpp"
class Abaddon {
public:
int DoMainLoop();
void StartDiscordThread();
void ActionConnect();
private:
Glib::RefPtr<Gtk::Application> m_gtk_app;
DiscordClient m_discord;
};

12
components/channels.cpp Normal file
View File

@ -0,0 +1,12 @@
#include "channels.hpp"
ChannelList::ChannelList() {
m_main = Gtk::manage(new Gtk::ScrolledWindow);
m_list = Gtk::manage(new Gtk::ListBox);
m_main->add(*m_list);
}
Gtk::Widget* ChannelList::GetRoot() const {
return m_main;
}

12
components/channels.hpp Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include <gtkmm.h>
class ChannelList {
public:
ChannelList();
Gtk::Widget *GetRoot() const;
protected:
Gtk::ListBox *m_list;
Gtk::ScrolledWindow *m_main;
};

85
discord/discord.cpp Normal file
View File

@ -0,0 +1,85 @@
#include "discord.hpp"
DiscordClient::DiscordClient() {}
void DiscordClient::Start() {
if (m_client_connected)
throw std::runtime_error("attempt to start client twice consecutively");
m_client_connected = true;
m_websocket.StartConnection(DiscordGateway);
m_websocket.SetJSONCallback(std::bind(&DiscordClient::HandleGatewayMessage, this, std::placeholders::_1));
}
void DiscordClient::Stop() {
if (!m_client_connected) return;
m_heartbeat_waiter.kill();
m_heartbeat_thread.join();
m_client_connected = false;
}
bool DiscordClient::IsStarted() const {
return m_client_connected;
}
void DiscordClient::HandleGatewayMessage(nlohmann::json j) {
GatewayMessage m;
try {
m = j;
} catch (std::exception &e) {
printf("Error decoding JSON. Discarding message: %s\n", e.what());
return;
}
switch (m.Opcode) {
case GatewayOp::Hello: {
HelloMessageData d = m.Data;
m_heartbeat_msec = d.HeartbeatInterval;
m_heartbeat_thread = std::thread(std::bind(&DiscordClient::HeartbeatThread, this));
} break;
case GatewayOp::HeartbeatAck: {
m_heartbeat_acked = true;
} break;
default:
printf("Unknown opcode %d\n", m.Opcode);
break;
}
}
void DiscordClient::HeartbeatThread() {
while (m_client_connected) {
if (!m_heartbeat_acked) {
printf("wow! a heartbeat wasn't acked! how could this happen?");
}
m_heartbeat_acked = false;
HeartbeatMessage msg;
msg.Sequence = m_last_sequence;
nlohmann::json j = msg;
m_websocket.Send(j.dump());
if (!m_heartbeat_waiter.wait_for(std::chrono::milliseconds(m_heartbeat_msec)))
break;
}
}
void from_json(const nlohmann::json &j, GatewayMessage &m) {
j.at("op").get_to(m.Opcode);
m.Data = j.at("d");
if (j.contains("t") && !j.at("t").is_null())
j.at("t").get_to(m.Type);
}
void from_json(const nlohmann::json &j, HelloMessageData &m) {
j.at("heartbeat_interval").get_to(m.HeartbeatInterval);
}
void to_json(nlohmann::json &j, const HeartbeatMessage &m) {
j["op"] = GatewayOp::Heartbeat;
if (m.Sequence == -1)
j["d"] = nullptr;
else
j["d"] = m.Sequence;
}

75
discord/discord.hpp Normal file
View File

@ -0,0 +1,75 @@
#pragma once
#include "websocket.hpp"
#include <nlohmann/json.hpp>
#include <thread>
enum class GatewayOp : int {
Heartbeat = 1,
Hello = 10,
HeartbeatAck = 11,
};
struct GatewayMessage {
GatewayOp Opcode;
nlohmann::json Data;
std::string Type;
friend void from_json(const nlohmann::json &j, GatewayMessage &m);
};
struct HelloMessageData {
int HeartbeatInterval;
friend void from_json(const nlohmann::json &j, HelloMessageData &m);
};
struct HeartbeatMessage : GatewayMessage {
int Sequence;
friend void to_json(nlohmann::json &j, const HeartbeatMessage &m);
};
// https://stackoverflow.com/questions/29775153/stopping-long-sleep-threads/29775639#29775639
class HeartbeatWaiter {
public:
template<class R, class P>
bool wait_for(std::chrono::duration<R, P> const &time) const {
std::unique_lock<std::mutex> lock(m);
return !cv.wait_for(lock, time, [&] { return terminate; });
}
void kill() {
std::unique_lock<std::mutex> lock(m);
terminate = true;
cv.notify_all();
}
private:
mutable std::condition_variable cv;
mutable std::mutex m;
bool terminate = false;
};
class DiscordClient {
public:
static const constexpr char *DiscordGateway = "wss://gateway.discord.gg/?v=6&encoding=json";
static const constexpr char *DiscordAPI = "https://discord.com/api";
public:
DiscordClient();
void Start();
void Stop();
bool IsStarted() const;
private:
void HandleGatewayMessage(nlohmann::json msg);
void HeartbeatThread();
Websocket m_websocket;
bool m_client_connected = false;
std::thread m_heartbeat_thread;
int m_last_sequence = -1;
int m_heartbeat_msec = 0;
HeartbeatWaiter m_heartbeat_waiter;
bool m_heartbeat_acked = true;
};

30
discord/websocket.cpp Normal file
View File

@ -0,0 +1,30 @@
#include "websocket.hpp"
#include <functional>
#include <nlohmann/json.hpp>
Websocket::Websocket() {}
void Websocket::StartConnection(std::string url) {
m_websocket.setUrl(url);
m_websocket.setOnMessageCallback(std::bind(&Websocket::OnMessage, this, std::placeholders::_1));
m_websocket.start();
}
void Websocket::SetJSONCallback(JSONCallback_t func) {
m_json_callback = func;
}
void Websocket::Send(const std::string &str) {
m_websocket.sendText(str);
}
void Websocket::OnMessage(const ix::WebSocketMessagePtr &msg) {
switch (msg->type) {
case ix::WebSocketMessageType::Message:
printf("%s\n", msg->str.c_str());
auto obj = nlohmann::json::parse(msg->str);
if (m_json_callback)
m_json_callback(obj);
break;
}
}

22
discord/websocket.hpp Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include <ixwebsocket/IXNetSystem.h>
#include <ixwebsocket/IXWebSocket.h>
#include <string>
#include <functional>
#include <nlohmann/json.hpp>
class Websocket {
public:
Websocket();
void StartConnection(std::string url);
using JSONCallback_t = std::function<void(nlohmann::json)>;
void SetJSONCallback(JSONCallback_t func);
void Send(const std::string &str);
private:
void OnMessage(const ix::WebSocketMessagePtr &msg);
JSONCallback_t m_json_callback;
ix::WebSocket m_websocket;
};

31
windows/mainwindow.cpp Normal file
View File

@ -0,0 +1,31 @@
#include "mainwindow.hpp"
#include "../abaddon.hpp"
MainWindow::MainWindow()
: m_main_box(Gtk::ORIENTATION_VERTICAL) {
set_default_size(800, 600);
m_menu_discord.set_label("Discord");
m_menu_discord.set_submenu(m_menu_discord_sub);
m_menu_discord_connect.set_label("Connect");
m_menu_discord_sub.append(m_menu_discord_connect);
m_menu_discord.set_submenu(m_menu_discord_sub);
m_menu_bar.append(m_menu_discord);
m_menu_discord_connect.signal_activate().connect([&] {
m_abaddon->ActionConnect(); // this feels maybe not too smart
});
m_main_box.add(m_menu_bar);
auto *channel_list = m_channel_list.GetRoot();
m_main_box.add(*channel_list);
add(m_main_box);
show_all_children();
}
void MainWindow::SetAbaddon(Abaddon* ptr) {
m_abaddon = ptr;
}

22
windows/mainwindow.hpp Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include "../components/channels.hpp"
#include <gtkmm.h>
class Abaddon;
class MainWindow : public Gtk::Window {
public:
MainWindow();
void SetAbaddon(Abaddon *ptr);
protected:
Gtk::Box m_main_box;
ChannelList m_channel_list;
Gtk::MenuBar m_menu_bar;
Gtk::MenuItem m_menu_discord;
Gtk::Menu m_menu_discord_sub;
Gtk::MenuItem m_menu_discord_connect;
Abaddon *m_abaddon = nullptr;
};