swaymux/tree/swaytree.h

225 lines
7.0 KiB
C
Raw Normal View History

2024-03-04 00:27:05 +01:00
//
// Created by grimmauld on 03.03.24.
//
#ifndef SWAYMUX_SWAYTREE_H
#define SWAYMUX_SWAYTREE_H
#include <nlohmann/json.hpp>
#include <utility>
#include <iostream>
2024-03-04 00:27:05 +01:00
using json = nlohmann::json;
#include "AbstractTreeNode.h"
#include "../sway_bindings/Sway.h"
2024-03-04 00:27:05 +01:00
namespace NodeType {
enum NodeType {
root, output, workspace, con, floating_con
};
static NodeType fromString(const std::string &str) {
if (str == "output") {
return output;
}
if (str == "workspace") {
return workspace;
}
if (str == "con") {
return con;
}
if (str == "floating_con") {
return floating_con;
}
return root;
}
}
namespace NodeLayout {
enum NodeLayout {
splith, splitv, stacked, tabbed, output
};
static NodeLayout fromString(const std::string &str) {
if (str == "splith") {
return splith;
}
if (str == "splitv") {
return splitv;
}
if (str == "stacked") {
return stacked;
}
if (str == "tabbed") {
return tabbed;
}
return output;
}
}
namespace NodeOrientation {
enum NodeOrientation {
vertical, horizontal, none
};
static NodeOrientation fromString(const std::string &str) {
if (str == "vertical") {
return vertical;
}
if (str == "horizontal") {
return horizontal;
}
return none;
}
}
struct SwayRecord {
explicit SwayRecord() :
id(0),
name("rootItem"),
type(NodeType::root),
current_border_width(0),
layout(NodeLayout::output),
orientation(NodeOrientation::none),
urgent(false),
sticky(false),
focused(false) {}
explicit SwayRecord(const json &rep) :
id(rep["id"]),
name(getName(rep)),
2024-03-04 00:27:05 +01:00
type(NodeType::fromString(rep["type"])),
border(rep["border"]),
current_border_width(rep["current_border_width"]),
layout(NodeLayout::fromString((rep["layout"]))),
orientation(NodeOrientation::fromString(rep["orientation"])),
urgent(rep["urgent"]),
sticky(rep["sticky"]),
focused(rep["focused"]) {};
const int id;
const std::string name;
const NodeType::NodeType type;
const std::string border;
const int current_border_width;
const NodeLayout::NodeLayout layout;
const NodeOrientation::NodeOrientation orientation;
const bool urgent;
const bool sticky;
bool focused;
2024-03-04 00:27:05 +01:00
[[nodiscard]] bool operator<(const SwayRecord &other) const {
return this->id < other.id;
}
[[nodiscard]] bool operator==(const SwayRecord &other) const {
return this->id == other.id;
}
private:
static std::string getName(const json& rep) {
if(rep["name"].is_null())
return "Untitled Container";
std::string internal = rep["name"];
if (internal == "__i3" && NodeType::fromString(rep["type"]) == NodeType::output)
return "Virtual Display";
if (internal == "__i3_scratch" && NodeType::fromString(rep["type"]) == NodeType::workspace)
return "Scratchpad";
return internal;
}
2024-03-04 00:27:05 +01:00
};
class SwayTreeNode : public AbstractTreeNode<SwayTreeNode> {
public:
SwayRecord node;
2024-03-04 00:27:05 +01:00
explicit SwayTreeNode(const json &rep, SwayTreeNode *parent = nullptr) : node(SwayRecord(rep)),
AbstractTreeNode(parent) {
for (const auto &child: rep["nodes"]) {
if (child.contains("app_id") && !child["app_id"].is_null() && ((std::string) child["app_id"]) == "swaymux")
continue;
2024-03-04 00:27:05 +01:00
auto childNode = std::make_unique<SwayTreeNode>(child, this);
this->appendChild(childNode);
}
for (const auto &child: rep["floating_nodes"]) {
if (child.contains("app_id") && !child["app_id"].is_null() && ((std::string) child["app_id"]) == "swaymux")
continue;
2024-03-04 00:27:05 +01:00
auto childNode = std::make_unique<SwayTreeNode>(child, this);
this->appendChild(childNode);
}
}
explicit SwayTreeNode(SwayTreeNode *parent = nullptr) : node(SwayRecord()), AbstractTreeNode(parent) {};
explicit SwayTreeNode(SwayRecord node, SwayTreeNode *parent = nullptr) : node(std::move(node)),
AbstractTreeNode(parent) {};
[[nodiscard]] bool operator<(const SwayTreeNode &other) const {
return this->node < other.node;
}
[[nodiscard]] QVariant data(int column) const override;
[[nodiscard]] QVariant headerData(int column) const override;
[[nodiscard]] int columnCount() const override { return 1; };
[[nodiscard]] SwayTreeNode *findFocused() {
std::function<bool(const SwayTreeNode *)> focused = [](const SwayTreeNode *testNode) {
return testNode->node.focused;
};
return this->findChildRecursive(focused);
}
[[nodiscard]] inline const SwayTreeNode *findRoot() const {
return this->findParentRecursive(matchNodeType(NodeType::root));
}
[[nodiscard]] inline const SwayTreeNode *findOutput() const {
return this->findParentRecursive(matchNodeType(NodeType::output));
}
[[nodiscard]] inline const SwayTreeNode *findWorkspace() const {
return this->findParentRecursive(matchNodeType(NodeType::workspace));
}
[[nodiscard]] inline std::set<SwayTreeNode *> accumulateContainers() const {
return accumulateMatchingChildrenRecursive(matchNodeType({NodeType::con, NodeType::floating_con}));
}
2024-03-08 10:53:30 +01:00
[[nodiscard]] std::set<std::string> accumulateWorkspaces() const {
auto workspaces = accumulateMatchingChildrenRecursive(matchNodeType(NodeType::workspace));
std::set<std::string> result;
std::transform(workspaces.begin(), workspaces.end(), std::inserter(result, result.begin()),
[](const SwayTreeNode *workspace) { return workspace->node.name; });
return result;
2024-03-08 10:53:30 +01:00
}
[[nodiscard]] SwayTreeNode * findById(const int id) {
return const_cast<SwayTreeNode *>(findChildRecursive([id](const SwayTreeNode *test) {
return test->node.id == id;
}));
}
private:
[[nodiscard]] static std::function<bool(const SwayTreeNode *)> matchNodeType(NodeType::NodeType type) {
return matchNodeType(std::vector{type});
}
[[nodiscard]] static std::function<bool(const SwayTreeNode *)>
matchNodeType(const std::vector<NodeType::NodeType>& types) {
return [types](const SwayTreeNode *testNode) {
return std::ranges::any_of(types.begin(), types.end(), [testNode](const auto t) {
return testNode->node.type == t;
});
};
}
[[nodiscard]] bool operator==(const SwayTreeNode * other) const {
return this->node == other->node;
}
2024-03-04 00:27:05 +01:00
};
#endif //SWAYMUX_SWAYTREE_H