quick commit
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
#include <gtk4-layer-shell/gtk4-layer-shell.h>
|
||||
#include <gtkmm.h>
|
||||
|
||||
#include "icons.hpp"
|
||||
#include "widgets/clock.hpp"
|
||||
#include "widgets/date.hpp"
|
||||
#include "widgets/tray.hpp"
|
||||
@@ -26,8 +25,8 @@ class Bar : public Gtk::Window {
|
||||
|
||||
Clock clock;
|
||||
Date date;
|
||||
WebWidget homeAssistant{ICON_HOME, "Home Assistant", "https://home.rivercry.com"};
|
||||
ControlCenter controlCenter{"\ue8bb", "Control Center"};
|
||||
WebWidget homeAssistant{"\ue88a", "Home Assistant", "https://home.rivercry.com"};
|
||||
ControlCenter controlCenter{"\ue88a", "Control Center"};
|
||||
|
||||
WorkspaceIndicator *workspaceIndicator = nullptr;
|
||||
TrayWidget *trayWidget = nullptr;
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "gtkmm/box.h"
|
||||
|
||||
class TodoEntry : public Gtk::Box {
|
||||
public:
|
||||
TodoEntry(int id, std::string text, sigc::signal<void(int)> signal_dismissed, sigc::signal<void(int, std::string)> signal_edited);
|
||||
|
||||
int get_id() const { return id; }
|
||||
std::string get_text() const { return text; }
|
||||
|
||||
private:
|
||||
int id;
|
||||
std::string text;
|
||||
sigc::signal<void(int)> signal_dismissed;
|
||||
sigc::signal<void(int, std::string)> signal_edited;
|
||||
|
||||
void on_dismiss_clicked();
|
||||
};
|
||||
31
include/helpers/command.hpp
Normal file
31
include/helpers/command.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
class CommandHelper {
|
||||
public:
|
||||
static std::string exec(const char *cmd) {
|
||||
std::array<char, 128> buffer;
|
||||
std::string result;
|
||||
std::unique_ptr<FILE, int(*)(FILE*)> pipe(popen(cmd, "r"), pclose);
|
||||
if (!pipe) {
|
||||
throw std::runtime_error("popen() failed!");
|
||||
}
|
||||
while (fgets(buffer.data(), static_cast<int>(buffer.size()), pipe.get()) != nullptr) {
|
||||
result += buffer.data();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void execNoOutput(std::string cmd) {
|
||||
std::string command = cmd + " > /dev/null 2>&1";
|
||||
int ret = std::system(command.c_str());
|
||||
if (ret != 0) {
|
||||
throw std::runtime_error("Command failed with return code: " + std::to_string(ret));
|
||||
}
|
||||
}
|
||||
};
|
||||
69
include/helpers/hypr.hpp
Normal file
69
include/helpers/hypr.hpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <string>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "helpers/command.hpp"
|
||||
|
||||
class HyprctlHelper {
|
||||
public:
|
||||
static nlohmann::json getMonitorData() {
|
||||
std::string result = CommandHelper::exec("hyprctl -j monitors");
|
||||
assert(!result.empty() && "Failed to get monitor data from hyprctl");
|
||||
|
||||
auto json = nlohmann::json::parse(result);
|
||||
|
||||
assert(json.is_array());
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
static nlohmann::json getWorkspaceData() {
|
||||
std::string result = CommandHelper::exec("hyprctl -j workspaces");
|
||||
assert(!result.empty() && "Failed to get workspace data from hyprctl");
|
||||
|
||||
auto json = nlohmann::json::parse(result);
|
||||
|
||||
assert(json.is_array());
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
static nlohmann::json getClientData() {
|
||||
std::string result = CommandHelper::exec("hyprctl -j clients");
|
||||
assert(!result.empty() && "Failed to get client data from hyprctl");
|
||||
|
||||
auto json = nlohmann::json::parse(result);
|
||||
|
||||
assert(json.is_array());
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
static void dispatchWorkspace(int workspaceNumber) {
|
||||
std::string out = "hyprctl dispatch workspace " + std::to_string(workspaceNumber);
|
||||
CommandHelper::execNoOutput(out.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
class HyprSocketHelper {
|
||||
public:
|
||||
static std::string getHyprlandSocketPath() {
|
||||
const char *hyprlandInstanceSignature = std::getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
||||
const char *xdgRuntimeDir = std::getenv("XDG_RUNTIME_DIR");
|
||||
|
||||
if (!xdgRuntimeDir || !hyprlandInstanceSignature) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string basePath = std::string(xdgRuntimeDir) + "/hypr/" + std::string(hyprlandInstanceSignature) + "/";
|
||||
std::string sock1 = basePath + ".socket2.sock";
|
||||
if (access(sock1.c_str(), F_OK) == 0) {
|
||||
return sock1;
|
||||
}
|
||||
|
||||
return std::string();
|
||||
}
|
||||
};
|
||||
52
include/helpers/socket.hpp
Normal file
52
include/helpers/socket.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sys/socket.h>
|
||||
#include <vector>
|
||||
|
||||
#include "helper/string.hpp"
|
||||
|
||||
class SocketHelper {
|
||||
typedef struct SocketMessage {
|
||||
std::string eventType;
|
||||
std::string eventData;
|
||||
} SocketMessage;
|
||||
|
||||
public:
|
||||
static std::vector<SocketMessage> parseSocketMessage(int socketFd, const std::string &delimiter) {
|
||||
char buffer[4096];
|
||||
std::string data;
|
||||
ssize_t bytesRead = recv(socketFd, buffer, sizeof(buffer) - 1, 0);
|
||||
if (bytesRead > 0) {
|
||||
buffer[bytesRead] = '\0';
|
||||
data = std::string(buffer);
|
||||
} else if (bytesRead == 0) {
|
||||
std::cerr << "Socket closed by peer" << std::endl;
|
||||
} else {
|
||||
std::cerr << "Error reading from socket" << std::endl;
|
||||
}
|
||||
|
||||
auto delimiterPos = data.find(delimiter);
|
||||
|
||||
if (delimiterPos == std::string::npos) {
|
||||
assert(false && "Delimiter not found in socket message");
|
||||
}
|
||||
|
||||
auto splitMessages = StringHelper::split(data, '\n');
|
||||
auto splitMessagesFinal = std::vector<SocketMessage>();
|
||||
for (auto splitMessage : splitMessages) {
|
||||
|
||||
|
||||
SocketMessage message;
|
||||
auto messageCommandVector = StringHelper::split(splitMessage, ">>");
|
||||
|
||||
message.eventType = messageCommandVector[0];
|
||||
message.eventData = messageCommandVector.size() > 1 ? messageCommandVector[1] : "";
|
||||
splitMessagesFinal.push_back(message);
|
||||
}
|
||||
|
||||
return splitMessagesFinal;
|
||||
}
|
||||
};
|
||||
40
include/helpers/string.hpp
Normal file
40
include/helpers/string.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
class StringHelper {
|
||||
public:
|
||||
static std::vector<std::string> split(const std::string &input, char delimiter) {
|
||||
std::vector<std::string> tokens;
|
||||
std::string token;
|
||||
for (char ch : input) {
|
||||
if (ch == delimiter) {
|
||||
if (!token.empty()) {
|
||||
tokens.push_back(token);
|
||||
token.clear();
|
||||
}
|
||||
} else {
|
||||
token += ch;
|
||||
}
|
||||
}
|
||||
if (!token.empty()) {
|
||||
tokens.push_back(token);
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
static std::vector<std::string> split(const std::string &input, std::string delimiter) {
|
||||
std::vector<std::string> tokens;
|
||||
size_t start = 0;
|
||||
size_t end = input.find(delimiter);
|
||||
while (end != std::string::npos) {
|
||||
tokens.push_back(input.substr(start, end - start));
|
||||
start = end + delimiter.length();
|
||||
end = input.find(delimiter, start);
|
||||
}
|
||||
tokens.push_back(input.substr(start));
|
||||
return tokens;
|
||||
}
|
||||
};
|
||||
17
include/helpers/system.hpp
Normal file
17
include/helpers/system.hpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
|
||||
class SystemHelper {
|
||||
public:
|
||||
static std::string read_file_to_string(const std::string &filePath) {
|
||||
std::ifstream file(filePath);
|
||||
if (!file.is_open()) {
|
||||
throw std::runtime_error("Could not open file: " + filePath);
|
||||
}
|
||||
std::string content((std::istreambuf_iterator<char>(file)),
|
||||
std::istreambuf_iterator<char>());
|
||||
file.close();
|
||||
return content;
|
||||
}
|
||||
};
|
||||
@@ -1,39 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
class SystemHelper {
|
||||
public:
|
||||
static std::string get_command_output(const char *cmd) {
|
||||
std::array<char, 128> buffer;
|
||||
std::string result;
|
||||
std::unique_ptr<FILE, int (*)(FILE *)> pipe(popen(cmd, "r"), pclose);
|
||||
|
||||
if (!pipe) {
|
||||
throw std::runtime_error("popen() failed!");
|
||||
}
|
||||
|
||||
// Read the output a chunk at a time until the stream ends
|
||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
|
||||
result += buffer.data();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Read an entire file into a string. Throws std::runtime_error on failure.
|
||||
static std::string read_file_to_string(const std::string &path) {
|
||||
std::ifstream in(path, std::ios::in | std::ios::binary);
|
||||
if (!in) {
|
||||
throw std::runtime_error("Failed to open file: " + path);
|
||||
}
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << in.rdbuf();
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define ICON_HOME "\ue88a"
|
||||
@@ -13,13 +13,6 @@ class HyprlandService {
|
||||
|
||||
public:
|
||||
static constexpr int kWorkspaceSlotCount = 7;
|
||||
const char *kMonitorCommand = "hyprctl monitors -j";
|
||||
const char *kWorkspaceCommand = "hyprctl workspaces -j";
|
||||
const char *kClientsCommand = "hyprctl clients -j";
|
||||
|
||||
struct WindowState {
|
||||
int hyprId = -1;
|
||||
};
|
||||
|
||||
struct WorkspaceState {
|
||||
int hyprId = -1;
|
||||
@@ -64,6 +57,10 @@ class HyprlandService {
|
||||
}
|
||||
|
||||
private:
|
||||
const char *kMonitorCommand = "hyprctl monitors -j";
|
||||
const char *kWorkspaceCommand = "hyprctl workspaces -j";
|
||||
const char *kClientsCommand = "hyprctl clients -j";
|
||||
|
||||
HyprlandService();
|
||||
~HyprlandService();
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "components/todoEntry.hpp"
|
||||
#include "services/todoAdapter.hpp"
|
||||
|
||||
class TodoService {
|
||||
public:
|
||||
TodoService(sigc::signal<void()> refreshSignal);
|
||||
~TodoService();
|
||||
|
||||
std::map<int, TodoEntry *> getTodos();
|
||||
void init();
|
||||
void removeTodo(int id);
|
||||
TodoEntry *addTodo(std::string text, bool emitSignal = true, bool persist = true);
|
||||
void updateTodo(int id, std::string text);
|
||||
|
||||
private:
|
||||
void load();
|
||||
|
||||
int nextId = 1;
|
||||
std::map<int, TodoEntry *> todos;
|
||||
sigc::signal<void()> refreshSignal;
|
||||
|
||||
std::unique_ptr<ITodoAdapter> adapter;
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct TodoRecord {
|
||||
int id;
|
||||
std::string text;
|
||||
};
|
||||
|
||||
class ITodoAdapter {
|
||||
public:
|
||||
virtual ~ITodoAdapter() = default;
|
||||
|
||||
virtual bool init() = 0;
|
||||
virtual std::vector<TodoRecord> listTodos() = 0;
|
||||
|
||||
virtual int addTodo(const std::string &text) = 0;
|
||||
virtual bool removeTodo(int id) = 0;
|
||||
virtual bool updateTodo(int id, const std::string &text) = 0;
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "components/popover.hpp"
|
||||
#include "services/todo.hpp"
|
||||
|
||||
class TodoPopover : public Popover {
|
||||
|
||||
public:
|
||||
TodoPopover(std::string icon, std::string title);
|
||||
|
||||
void update();
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
TodoService *todoService = nullptr;
|
||||
Gtk::Box container;
|
||||
Gtk::Box inputArea;
|
||||
Gtk::Box *todoList = nullptr;
|
||||
};
|
||||
Reference in New Issue
Block a user