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>
|
|
|
|
|
|
|
|
using json = nlohmann::json;
|
|
|
|
|
|
|
|
#include "AbstractTreeNode.h"
|
2024-03-08 13:13:28 +01:00
|
|
|
#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"]),
|
2024-03-07 17:37:18 +01:00
|
|
|
name(rep["name"].is_null() ? "untitled container" : rep["name"]),
|
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;
|
|
|
|
const bool focused;
|
|
|
|
|
|
|
|
[[nodiscard]] bool operator<(const SwayRecord &other) const {
|
|
|
|
return this->id < other.id;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] bool operator==(const SwayRecord &other) const {
|
|
|
|
return this->id == other.id;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class SwayTreeNode : public AbstractTreeNode<SwayTreeNode> {
|
|
|
|
public:
|
|
|
|
const SwayRecord node;
|
|
|
|
|
|
|
|
explicit SwayTreeNode(const json &rep, SwayTreeNode *parent = nullptr) : node(SwayRecord(rep)),
|
|
|
|
AbstractTreeNode(parent) {
|
|
|
|
for (const auto &child: rep["nodes"]) {
|
|
|
|
auto childNode = std::make_unique<SwayTreeNode>(child, this);
|
|
|
|
this->appendChild(childNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
for (const auto &child: rep["floating_nodes"]) {
|
|
|
|
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; };
|
2024-03-07 11:20:26 +01:00
|
|
|
|
|
|
|
[[nodiscard]] const SwayTreeNode *findFocused() const {
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2024-03-08 10:53:30 +01:00
|
|
|
[[nodiscard]] std::set<std::string> accumulateWorkspaces() const {
|
|
|
|
std::set<std::string> workspaces;
|
|
|
|
if (node.type == NodeType::workspace) {
|
|
|
|
workspaces.insert(node.name);
|
|
|
|
return workspaces; // assumption: no workspaces within workspaces. This might be dangerous for the future, but is currently not a sway feature.
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < childCount(); ++i) {
|
|
|
|
auto child_workspaces = child(i)->accumulateWorkspaces();
|
|
|
|
workspaces.insert(child_workspaces.cbegin(), child_workspaces.cend());
|
|
|
|
}
|
|
|
|
return workspaces;
|
|
|
|
}
|
|
|
|
|
2024-03-07 11:20:26 +01:00
|
|
|
private:
|
|
|
|
[[nodiscard]] static std::function<bool(const SwayTreeNode *)> matchNodeType(const NodeType::NodeType type) {
|
|
|
|
return [type](const SwayTreeNode *testNode) {
|
|
|
|
return testNode->node.type == type;
|
|
|
|
};
|
|
|
|
}
|
2024-03-04 00:27:05 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#endif //SWAYMUX_SWAYTREE_H
|