forked from OpenGamers/abaddon
settings, token entry, receive READY
This commit is contained in:
parent
18af78e6af
commit
3c3fe3b9f7
3
.gitignore
vendored
3
.gitignore
vendored
@ -348,3 +348,6 @@ MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
abaddon.ini
|
||||
testdata/
|
||||
|
@ -143,15 +143,19 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="abaddon.cpp" />
|
||||
<ClCompile Include="components\channels.cpp" />
|
||||
<ClCompile Include="dialogs\token.cpp" />
|
||||
<ClCompile Include="discord\discord.cpp" />
|
||||
<ClCompile Include="discord\websocket.cpp" />
|
||||
<ClCompile Include="settings.cpp" />
|
||||
<ClCompile Include="windows\mainwindow.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="components\channels.hpp" />
|
||||
<ClInclude Include="abaddon.hpp" />
|
||||
<ClInclude Include="dialogs\token.hpp" />
|
||||
<ClInclude Include="discord\discord.hpp" />
|
||||
<ClInclude Include="discord\websocket.hpp" />
|
||||
<ClInclude Include="settings.hpp" />
|
||||
<ClInclude Include="windows\mainwindow.hpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
@ -30,6 +30,12 @@
|
||||
<ClCompile Include="discord\discord.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="settings.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dialogs\token.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="windows\mainwindow.hpp">
|
||||
@ -47,5 +53,11 @@
|
||||
<ClInclude Include="abaddon.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="settings.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="dialogs\token.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
96
abaddon.cpp
96
abaddon.cpp
@ -1,44 +1,92 @@
|
||||
#include <gtkmm.h>
|
||||
#include "discord/discord.hpp"
|
||||
#include "windows/mainwindow.hpp"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include "discord/discord.hpp"
|
||||
#include "dialogs/token.hpp"
|
||||
#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);
|
||||
Abaddon::Abaddon()
|
||||
: m_settings("abaddon.ini") {
|
||||
m_discord.SetAbaddon(this);
|
||||
LoadFromSettings();
|
||||
}
|
||||
|
||||
void Abaddon::StartDiscordThread() {
|
||||
Abaddon::~Abaddon() {
|
||||
m_settings.Close();
|
||||
m_discord.Stop();
|
||||
}
|
||||
|
||||
int Abaddon::StartGTK() {
|
||||
m_gtk_app = Gtk::Application::create("com.github.lorpus.abaddon");
|
||||
|
||||
m_main_window = std::make_unique<MainWindow>();
|
||||
m_main_window->SetAbaddon(this);
|
||||
m_main_window->set_title("Abaddon");
|
||||
m_main_window->show();
|
||||
m_main_window->UpdateMenuStatus();
|
||||
|
||||
m_gtk_app->signal_shutdown().connect([&]() {
|
||||
StopDiscord();
|
||||
});
|
||||
|
||||
if (!m_settings.IsValid()) {
|
||||
Gtk::MessageDialog dlg(*m_main_window, "The settings file could not be created!", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
||||
dlg.run();
|
||||
}
|
||||
|
||||
return m_gtk_app->run(*m_main_window);
|
||||
}
|
||||
|
||||
void Abaddon::LoadFromSettings() {
|
||||
std::string token = m_settings.GetSetting("discord", "token");
|
||||
if (token.size()) {
|
||||
m_discord_token = token;
|
||||
}
|
||||
}
|
||||
|
||||
void Abaddon::StartDiscord() {
|
||||
m_discord.Start();
|
||||
}
|
||||
|
||||
void Abaddon::StopDiscord() {
|
||||
m_discord.Stop();
|
||||
}
|
||||
|
||||
bool Abaddon::IsDiscordActive() const {
|
||||
return m_discord.IsStarted();
|
||||
}
|
||||
|
||||
std::string Abaddon::GetDiscordToken() const {
|
||||
return m_discord_token;
|
||||
}
|
||||
|
||||
void Abaddon::ActionConnect() {
|
||||
if (!m_discord.IsStarted())
|
||||
StartDiscordThread();
|
||||
StartDiscord();
|
||||
m_main_window->UpdateMenuStatus();
|
||||
}
|
||||
|
||||
void Abaddon::ActionDisconnect() {
|
||||
if (m_discord.IsStarted())
|
||||
StopDiscord();
|
||||
m_main_window->UpdateMenuStatus();
|
||||
}
|
||||
|
||||
void Abaddon::ActionSetToken() {
|
||||
TokenDialog dlg(*m_main_window);
|
||||
auto response = dlg.run();
|
||||
if (response == Gtk::RESPONSE_OK) {
|
||||
m_discord_token = dlg.GetToken();
|
||||
m_main_window->UpdateMenuStatus();
|
||||
m_settings.SetSetting("discord", "token", m_discord_token);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
Abaddon abaddon;
|
||||
return abaddon.DoMainLoop();
|
||||
return abaddon.StartGTK();
|
||||
}
|
||||
|
23
abaddon.hpp
23
abaddon.hpp
@ -1,14 +1,33 @@
|
||||
#include <gtkmm.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include "discord/discord.hpp"
|
||||
#include "windows/mainwindow.hpp"
|
||||
#include "settings.hpp"
|
||||
|
||||
class Abaddon {
|
||||
public:
|
||||
int DoMainLoop();
|
||||
void StartDiscordThread();
|
||||
Abaddon();
|
||||
~Abaddon();
|
||||
|
||||
int StartGTK();
|
||||
void StartDiscord();
|
||||
void StopDiscord();
|
||||
|
||||
void LoadFromSettings();
|
||||
|
||||
void ActionConnect();
|
||||
void ActionDisconnect();
|
||||
void ActionSetToken();
|
||||
|
||||
std::string GetDiscordToken() const;
|
||||
bool IsDiscordActive() const;
|
||||
|
||||
private:
|
||||
std::string m_discord_token;
|
||||
|
||||
Glib::RefPtr<Gtk::Application> m_gtk_app;
|
||||
DiscordClient m_discord;
|
||||
SettingsManager m_settings;
|
||||
std::unique_ptr<MainWindow> m_main_window; // wah wah cant create a gtkstylecontext fuck you
|
||||
};
|
34
dialogs/token.cpp
Normal file
34
dialogs/token.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include "token.hpp"
|
||||
|
||||
TokenDialog::TokenDialog(Gtk::Window &parent)
|
||||
: Gtk::Dialog("Set Token", parent, true)
|
||||
, m_layout(Gtk::ORIENTATION_VERTICAL)
|
||||
, m_bbox(Gtk::ORIENTATION_HORIZONTAL)
|
||||
, m_ok("OK")
|
||||
, m_cancel("Cancel") {
|
||||
set_default_size(300, 50);
|
||||
|
||||
m_ok.signal_clicked().connect([&]() {
|
||||
m_token = m_entry.get_text();
|
||||
response(Gtk::RESPONSE_OK);
|
||||
});
|
||||
|
||||
m_cancel.signal_clicked().connect([&]() {
|
||||
response(Gtk::RESPONSE_CANCEL);
|
||||
});
|
||||
|
||||
m_bbox.pack_start(m_ok, Gtk::PACK_SHRINK);
|
||||
m_bbox.pack_start(m_cancel, Gtk::PACK_SHRINK);
|
||||
m_bbox.set_layout(Gtk::BUTTONBOX_END);
|
||||
|
||||
m_entry.set_hexpand(true);
|
||||
m_layout.add(m_entry);
|
||||
m_layout.add(m_bbox);
|
||||
get_content_area()->add(m_layout);
|
||||
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
std::string TokenDialog::GetToken() {
|
||||
return m_token;
|
||||
}
|
19
dialogs/token.hpp
Normal file
19
dialogs/token.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <gtkmm.h>
|
||||
#include <string>
|
||||
|
||||
class TokenDialog : public Gtk::Dialog {
|
||||
public:
|
||||
TokenDialog(Gtk::Window &parent);
|
||||
std::string GetToken();
|
||||
|
||||
protected:
|
||||
Gtk::Box m_layout;
|
||||
Gtk::Button m_ok;
|
||||
Gtk::Button m_cancel;
|
||||
Gtk::ButtonBox m_bbox;
|
||||
Gtk::Entry m_entry;
|
||||
|
||||
private:
|
||||
std::string m_token;
|
||||
};
|
@ -1,10 +1,18 @@
|
||||
#include "../abaddon.hpp"
|
||||
#include "discord.hpp"
|
||||
#include <cassert>
|
||||
|
||||
DiscordClient::DiscordClient() {}
|
||||
DiscordClient::DiscordClient() {
|
||||
LoadEventMap();
|
||||
}
|
||||
|
||||
void DiscordClient::SetAbaddon(Abaddon *ptr) {
|
||||
m_abaddon = ptr;
|
||||
}
|
||||
|
||||
void DiscordClient::Start() {
|
||||
if (m_client_connected)
|
||||
throw std::runtime_error("attempt to start client twice consecutively");
|
||||
assert(!m_client_connected);
|
||||
assert(!m_websocket.IsOpen());
|
||||
|
||||
m_client_connected = true;
|
||||
m_websocket.StartConnection(DiscordGateway);
|
||||
@ -13,9 +21,11 @@ void DiscordClient::Start() {
|
||||
|
||||
void DiscordClient::Stop() {
|
||||
if (!m_client_connected) return;
|
||||
|
||||
m_heartbeat_waiter.kill();
|
||||
m_heartbeat_thread.join();
|
||||
m_client_connected = false;
|
||||
m_websocket.Stop();
|
||||
}
|
||||
|
||||
bool DiscordClient::IsStarted() const {
|
||||
@ -36,16 +46,33 @@ void DiscordClient::HandleGatewayMessage(nlohmann::json j) {
|
||||
HelloMessageData d = m.Data;
|
||||
m_heartbeat_msec = d.HeartbeatInterval;
|
||||
m_heartbeat_thread = std::thread(std::bind(&DiscordClient::HeartbeatThread, this));
|
||||
SendIdentify();
|
||||
} break;
|
||||
case GatewayOp::HeartbeatAck: {
|
||||
m_heartbeat_acked = true;
|
||||
} break;
|
||||
case GatewayOp::Event: {
|
||||
auto iter = m_event_map.find(m.Type);
|
||||
if (iter == m_event_map.end()) {
|
||||
printf("Unknown event %s\n", m.Type.c_str());
|
||||
break;
|
||||
}
|
||||
switch (iter->second) {
|
||||
case GatewayEvent::READY: {
|
||||
HandleGatewayReady(m);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
printf("Unknown opcode %d\n", m.Opcode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DiscordClient::HandleGatewayReady(const GatewayMessage &msg) {
|
||||
|
||||
}
|
||||
|
||||
void DiscordClient::HeartbeatThread() {
|
||||
while (m_client_connected) {
|
||||
if (!m_heartbeat_acked) {
|
||||
@ -57,13 +84,28 @@ void DiscordClient::HeartbeatThread() {
|
||||
HeartbeatMessage msg;
|
||||
msg.Sequence = m_last_sequence;
|
||||
nlohmann::json j = msg;
|
||||
m_websocket.Send(j.dump());
|
||||
m_websocket.Send(j);
|
||||
|
||||
if (!m_heartbeat_waiter.wait_for(std::chrono::milliseconds(m_heartbeat_msec)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DiscordClient::SendIdentify() {
|
||||
auto token = m_abaddon->GetDiscordToken();
|
||||
assert(token.size());
|
||||
IdentifyMessage msg;
|
||||
msg.Properties.OS = "OpenBSD";
|
||||
msg.Properties.Device = GatewayIdentity;
|
||||
msg.Properties.Browser = GatewayIdentity;
|
||||
msg.Token = token;
|
||||
m_websocket.Send(msg);
|
||||
}
|
||||
|
||||
void DiscordClient::LoadEventMap() {
|
||||
m_event_map["READY"] = GatewayEvent::READY;
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json &j, GatewayMessage &m) {
|
||||
j.at("op").get_to(m.Opcode);
|
||||
m.Data = j.at("d");
|
||||
@ -76,6 +118,22 @@ void from_json(const nlohmann::json &j, HelloMessageData &m) {
|
||||
j.at("heartbeat_interval").get_to(m.HeartbeatInterval);
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const IdentifyProperties &m) {
|
||||
j["$os"] = m.OS;
|
||||
j["$browser"] = m.Browser;
|
||||
j["$device"] = m.Device;
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const IdentifyMessage &m) {
|
||||
j["op"] = GatewayOp::Identify;
|
||||
j["d"] = nlohmann::json::object();
|
||||
j["d"]["token"] = m.Token;
|
||||
j["d"]["properties"] = m.Properties;
|
||||
|
||||
if (m.LargeThreshold)
|
||||
j["d"]["large_threshold"] = m.LargeThreshold;
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const HeartbeatMessage &m) {
|
||||
j["op"] = GatewayOp::Heartbeat;
|
||||
if (m.Sequence == -1)
|
||||
|
@ -2,13 +2,20 @@
|
||||
#include "websocket.hpp"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
|
||||
enum class GatewayOp : int {
|
||||
Event = 0,
|
||||
Heartbeat = 1,
|
||||
Identify = 2,
|
||||
Hello = 10,
|
||||
HeartbeatAck = 11,
|
||||
};
|
||||
|
||||
enum class GatewayEvent : int {
|
||||
READY,
|
||||
};
|
||||
|
||||
struct GatewayMessage {
|
||||
GatewayOp Opcode;
|
||||
nlohmann::json Data;
|
||||
@ -23,6 +30,28 @@ struct HelloMessageData {
|
||||
friend void from_json(const nlohmann::json &j, HelloMessageData &m);
|
||||
};
|
||||
|
||||
struct ReadyEventData {
|
||||
std::string AnalyticsToken; // opt
|
||||
|
||||
};
|
||||
|
||||
struct IdentifyProperties {
|
||||
std::string OS;
|
||||
std::string Browser;
|
||||
std::string Device;
|
||||
|
||||
friend void to_json(nlohmann::json &j, const IdentifyProperties &m);
|
||||
};
|
||||
|
||||
struct IdentifyMessage : GatewayMessage {
|
||||
std::string Token;
|
||||
IdentifyProperties Properties;
|
||||
bool DoesSupportCompression = false;
|
||||
int LargeThreshold = 0;
|
||||
|
||||
friend void to_json(nlohmann::json &j, const IdentifyMessage &m);
|
||||
};
|
||||
|
||||
struct HeartbeatMessage : GatewayMessage {
|
||||
int Sequence;
|
||||
|
||||
@ -49,23 +78,32 @@ private:
|
||||
bool terminate = false;
|
||||
};
|
||||
|
||||
class Abaddon;
|
||||
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";
|
||||
static const constexpr char *GatewayIdentity = "Discord";
|
||||
|
||||
public:
|
||||
DiscordClient();
|
||||
void SetAbaddon(Abaddon *ptr);
|
||||
void Start();
|
||||
void Stop();
|
||||
bool IsStarted() const;
|
||||
|
||||
private:
|
||||
void HandleGatewayMessage(nlohmann::json msg);
|
||||
void HandleGatewayReady(const GatewayMessage &msg);
|
||||
void HeartbeatThread();
|
||||
void SendIdentify();
|
||||
|
||||
Abaddon *m_abaddon = nullptr;
|
||||
|
||||
Websocket m_websocket;
|
||||
bool m_client_connected = false;
|
||||
std::unordered_map<std::string, GatewayEvent> m_event_map;
|
||||
void LoadEventMap();
|
||||
|
||||
std::thread m_heartbeat_thread;
|
||||
int m_last_sequence = -1;
|
||||
|
@ -10,21 +10,38 @@ void Websocket::StartConnection(std::string url) {
|
||||
m_websocket.start();
|
||||
}
|
||||
|
||||
void Websocket::Stop() {
|
||||
m_websocket.stop();
|
||||
}
|
||||
|
||||
bool Websocket::IsOpen() const {
|
||||
auto state = m_websocket.getReadyState();
|
||||
return state == ix::ReadyState::Open;
|
||||
}
|
||||
|
||||
void Websocket::SetJSONCallback(JSONCallback_t func) {
|
||||
m_json_callback = func;
|
||||
}
|
||||
|
||||
void Websocket::Send(const std::string &str) {
|
||||
printf("sending %s\n", str.c_str());
|
||||
m_websocket.sendText(str);
|
||||
}
|
||||
|
||||
void Websocket::Send(const nlohmann::json &j) {
|
||||
Send(j.dump());
|
||||
}
|
||||
|
||||
void Websocket::OnMessage(const ix::WebSocketMessagePtr &msg) {
|
||||
switch (msg->type) {
|
||||
case ix::WebSocketMessageType::Message:
|
||||
printf("%s\n", msg->str.c_str());
|
||||
case ix::WebSocketMessageType::Message: {
|
||||
if (msg->str.size() > 1000)
|
||||
printf("%s\n", msg->str.substr(0, 1000).c_str());
|
||||
else
|
||||
printf("%s\n", msg->str.c_str());
|
||||
auto obj = nlohmann::json::parse(msg->str);
|
||||
if (m_json_callback)
|
||||
m_json_callback(obj);
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,9 @@ public:
|
||||
using JSONCallback_t = std::function<void(nlohmann::json)>;
|
||||
void SetJSONCallback(JSONCallback_t func);
|
||||
void Send(const std::string &str);
|
||||
void Send(const nlohmann::json &j);
|
||||
void Stop();
|
||||
bool IsOpen() const;
|
||||
|
||||
private:
|
||||
void OnMessage(const ix::WebSocketMessagePtr &msg);
|
||||
|
23
settings.cpp
Normal file
23
settings.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "settings.hpp"
|
||||
|
||||
SettingsManager::SettingsManager(std::string filename)
|
||||
: m_filename(filename) {
|
||||
auto rc = m_ini.LoadFile(filename.c_str());
|
||||
m_ok = rc == SI_OK;
|
||||
}
|
||||
|
||||
std::string SettingsManager::GetSetting(std::string section, std::string key, std::string fallback) {
|
||||
return m_ini.GetValue(section.c_str(), key.c_str(), fallback.c_str());
|
||||
}
|
||||
|
||||
void SettingsManager::SetSetting(std::string section, std::string key, std::string value) {
|
||||
m_ini.SetValue(section.c_str(), key.c_str(), value.c_str());
|
||||
}
|
||||
|
||||
bool SettingsManager::IsValid() const {
|
||||
return m_ok;
|
||||
}
|
||||
|
||||
void SettingsManager::Close() {
|
||||
m_ini.SaveFile(m_filename.c_str());
|
||||
}
|
18
settings.hpp
Normal file
18
settings.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <SimpleIni.h>
|
||||
|
||||
class SettingsManager {
|
||||
public:
|
||||
SettingsManager(std::string filename);
|
||||
|
||||
void Close();
|
||||
std::string GetSetting(std::string section, std::string key, std::string fallback = "");
|
||||
void SetSetting(std::string section, std::string key, std::string value);
|
||||
bool IsValid() const;
|
||||
|
||||
private:
|
||||
bool m_ok;
|
||||
std::string m_filename;
|
||||
CSimpleIniA m_ini;
|
||||
};
|
@ -1,14 +1,21 @@
|
||||
#include "mainwindow.hpp"
|
||||
#include "../abaddon.hpp"
|
||||
|
||||
MainWindow::MainWindow()
|
||||
: m_main_box(Gtk::ORIENTATION_VERTICAL) {
|
||||
MainWindow::MainWindow() {
|
||||
set_default_size(800, 600);
|
||||
|
||||
m_main_box.set_orientation(Gtk::ORIENTATION_VERTICAL);
|
||||
|
||||
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_connect.set_sensitive(false);
|
||||
m_menu_discord_disconnect.set_label("Disconnect");
|
||||
m_menu_discord_disconnect.set_sensitive(false);
|
||||
m_menu_discord_set_token.set_label("Set Token");
|
||||
m_menu_discord_sub.append(m_menu_discord_connect);
|
||||
m_menu_discord_sub.append(m_menu_discord_disconnect);
|
||||
m_menu_discord_sub.append(m_menu_discord_set_token);
|
||||
m_menu_discord.set_submenu(m_menu_discord_sub);
|
||||
m_menu_bar.append(m_menu_discord);
|
||||
|
||||
@ -16,6 +23,14 @@ MainWindow::MainWindow()
|
||||
m_abaddon->ActionConnect(); // this feels maybe not too smart
|
||||
});
|
||||
|
||||
m_menu_discord_disconnect.signal_activate().connect([&] {
|
||||
m_abaddon->ActionDisconnect();
|
||||
});
|
||||
|
||||
m_menu_discord_set_token.signal_activate().connect([&] {
|
||||
m_abaddon->ActionSetToken();
|
||||
});
|
||||
|
||||
m_main_box.add(m_menu_bar);
|
||||
|
||||
auto *channel_list = m_channel_list.GetRoot();
|
||||
@ -26,6 +41,16 @@ MainWindow::MainWindow()
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
void MainWindow::SetAbaddon(Abaddon* ptr) {
|
||||
void MainWindow::UpdateMenuStatus() {
|
||||
// Connect
|
||||
std::string token = m_abaddon->GetDiscordToken();
|
||||
bool discord_active = m_abaddon->IsDiscordActive();
|
||||
m_menu_discord_connect.set_sensitive(token.size() > 0 && !discord_active);
|
||||
|
||||
// Disconnect
|
||||
m_menu_discord_disconnect.set_sensitive(discord_active);
|
||||
}
|
||||
|
||||
void MainWindow::SetAbaddon(Abaddon *ptr) {
|
||||
m_abaddon = ptr;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ class MainWindow : public Gtk::Window {
|
||||
public:
|
||||
MainWindow();
|
||||
void SetAbaddon(Abaddon *ptr);
|
||||
void UpdateMenuStatus();
|
||||
|
||||
protected:
|
||||
Gtk::Box m_main_box;
|
||||
@ -17,6 +18,8 @@ protected:
|
||||
Gtk::MenuItem m_menu_discord;
|
||||
Gtk::Menu m_menu_discord_sub;
|
||||
Gtk::MenuItem m_menu_discord_connect;
|
||||
Gtk::MenuItem m_menu_discord_disconnect;
|
||||
Gtk::MenuItem m_menu_discord_set_token;
|
||||
|
||||
Abaddon *m_abaddon = nullptr;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user