sway tree
This commit is contained in:
parent
f4a81cfa32
commit
4a6989f5ea
19 changed files with 570 additions and 95 deletions
|
@ -22,6 +22,14 @@ set(PROJECT_SOURCES
|
|||
${TS_FILES}
|
||||
tree/pstree.cpp
|
||||
tree/PsTreeModel.cpp
|
||||
sway_bindings/Formatter.h
|
||||
sway_bindings/Sway.cpp
|
||||
tree/swaytree.h
|
||||
tree/swaytree.cpp
|
||||
tree/AbstractTreeModel.h
|
||||
tree/AbstractTreeModel.h
|
||||
tree/SwayTreeModel.h
|
||||
tree/SwayTreeModel.cpp
|
||||
)
|
||||
|
||||
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
|
|
16
main.cpp
16
main.cpp
|
@ -1,6 +1,6 @@
|
|||
#include "mainwindow.h"
|
||||
#include "tree/pstree.h"
|
||||
#include "tree/PsTreeModel.h"
|
||||
#include "sway_bindings/Sway.h"
|
||||
#include "tree/swaytree.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QLocale>
|
||||
|
@ -9,11 +9,23 @@
|
|||
#include <QStringList>
|
||||
#include <QScreen>
|
||||
#include <QTreeView>
|
||||
#include<iostream>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
auto sway = Sway();
|
||||
auto resp = sway.sendIPC(SWAY_GET_TREE);
|
||||
json rep = json::parse(resp.msg);
|
||||
auto rootRecord = SwayRecord(rep);
|
||||
|
||||
QApplication a(argc, argv);
|
||||
QCoreApplication::setOrganizationName("Grimmauld");
|
||||
QCoreApplication::setApplicationName("SwayMux");
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "mainwindow.h"
|
||||
#include "./ui_mainwindow.h"
|
||||
#include "tree/PsTreeModel.h"
|
||||
#include "tree/SwayTreeModel.h"
|
||||
#include <QScreen>
|
||||
#include <QTimer>
|
||||
|
||||
|
@ -8,7 +9,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
: QMainWindow(parent), ui(new Ui::MainWindow) {
|
||||
ui->setupUi(this);
|
||||
|
||||
model = new PsTreeModel(ui->treeView);
|
||||
model = new SwayTreeModel(ui->treeView);
|
||||
modelUpdateTimer = new QTimer(this);
|
||||
connect(modelUpdateTimer, &QTimer::timeout, this, QOverload<>::of(&MainWindow::update));
|
||||
modelUpdateTimer->start(1000);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <QMainWindow>
|
||||
#include "tree/PsTreeModel.h"
|
||||
#include "tree/SwayTreeModel.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
|
@ -22,7 +23,7 @@ public:
|
|||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
PsTreeModel* model;
|
||||
SwayTreeModel* model;
|
||||
QTimer* modelUpdateTimer;
|
||||
};
|
||||
#endif // MAINWINDOW_H
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
<widget class="QTreeView" name="treeView">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>24</pointsize>
|
||||
<pointsize>20</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
|
|
41
sway_bindings/Formatter.h
Normal file
41
sway_bindings/Formatter.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// Created by grimmauld on 03.03.24.
|
||||
// https://stackoverflow.com/questions/12261915/how-to-throw-stdexceptions-with-variable-messages
|
||||
//
|
||||
|
||||
#ifndef IPCSWAYTEST_FORMATTER_H
|
||||
#define IPCSWAYTEST_FORMATTER_H
|
||||
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
|
||||
class Formatter
|
||||
{
|
||||
public:
|
||||
Formatter() = default;
|
||||
~Formatter() = default;
|
||||
|
||||
template <typename Type>
|
||||
Formatter & operator << (const Type & value)
|
||||
{
|
||||
stream_ << value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string str() const { return stream_.str(); }
|
||||
explicit operator std::string () const { return stream_.str(); }
|
||||
|
||||
enum ConvertToString
|
||||
{
|
||||
to_str
|
||||
};
|
||||
std::string operator >> (ConvertToString) { return stream_.str(); }
|
||||
|
||||
Formatter(const Formatter &) = delete;
|
||||
|
||||
private:
|
||||
std::stringstream stream_;
|
||||
// Formatter & operator = (Formatter &);
|
||||
};
|
||||
|
||||
#endif //IPCSWAYTEST_FORMATTER_H
|
37
sway_bindings/Sway.cpp
Normal file
37
sway_bindings/Sway.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// Created by grimmauld on 03.03.24.
|
||||
//
|
||||
|
||||
#include "Sway.h"
|
||||
|
||||
swaymsg Sway::sendIPC(const swaymsg &query) const {
|
||||
if (send(socketfd, query.asBuffer(), query.size(), 0) == -1) {
|
||||
throw std::runtime_error("Swaysock: Error on send() call");
|
||||
}
|
||||
|
||||
return swaymsg::fromSock(socketfd);
|
||||
}
|
||||
|
||||
Sway::Sway() : socketfd(socket(AF_UNIX, SOCK_STREAM, 0)) {
|
||||
initializeSocket();
|
||||
}
|
||||
|
||||
void Sway::initializeSocket() const {
|
||||
auto *sockaddr = std::getenv("SWAYSOCK");
|
||||
if (sockaddr == nullptr) {
|
||||
throw std::runtime_error("Binding socket: reading SWAYSOCK env var failed");
|
||||
}
|
||||
|
||||
if (socketfd == -1) {
|
||||
throw std::runtime_error("Binding socket: could not get file descriptor");
|
||||
}
|
||||
|
||||
struct sockaddr_un swaysock{};
|
||||
swaysock.sun_family = AF_UNIX;
|
||||
strcpy(swaysock.sun_path, sockaddr);
|
||||
auto dlen = strlen(swaysock.sun_path) + sizeof(swaysock.sun_family);
|
||||
|
||||
if (connect(socketfd, (struct sockaddr *) &swaysock, dlen) == -1) {
|
||||
throw std::runtime_error("Binding socket: could not connect to socket");
|
||||
}
|
||||
}
|
23
sway_bindings/Sway.h
Normal file
23
sway_bindings/Sway.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// Created by grimmauld on 03.03.24.
|
||||
//
|
||||
|
||||
#ifndef IPCSWAYTEST_SWAY_H
|
||||
#define IPCSWAYTEST_SWAY_H
|
||||
|
||||
#include "swaymsg.h"
|
||||
|
||||
class Sway {
|
||||
protected:
|
||||
const int socketfd;
|
||||
|
||||
public:
|
||||
explicit Sway();
|
||||
|
||||
void initializeSocket() const;
|
||||
|
||||
[[nodiscard]] swaymsg sendIPC(const swaymsg& query) const;
|
||||
};
|
||||
|
||||
|
||||
#endif //IPCSWAYTEST_SWAY_H
|
103
sway_bindings/swaymsg.h
Normal file
103
sway_bindings/swaymsg.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
//
|
||||
// Created by grimmauld on 03.03.24.
|
||||
//
|
||||
|
||||
#ifndef IPCSWAYTEST_SWAYMSG_H
|
||||
#define IPCSWAYTEST_SWAYMSG_H
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include "Formatter.h"
|
||||
|
||||
struct swaymsg {
|
||||
explicit swaymsg(const unsigned int payloadType, const char *msg) : swaymsg(payloadType, msg,
|
||||
msg == nullptr ? 0 : strlen(msg)) {};
|
||||
|
||||
explicit swaymsg(const unsigned int payloadType, const char *msg, const unsigned int payload_len)
|
||||
: payload_len(payload_len), payload_type(payloadType) {
|
||||
|
||||
this->msg = static_cast<char *>(std::malloc(payload_len));
|
||||
std::memcpy(this->msg, msg, payload_len);
|
||||
|
||||
buff = new unsigned char [size()];
|
||||
std::memcpy(buff, magic, strlen(magic));
|
||||
std::memcpy(buff + (unsigned int) strlen(magic), &payload_len, sizeof(payload_len));
|
||||
std::memcpy(buff + (unsigned int) strlen(magic) + sizeof(payload_len), &payload_type, sizeof(payload_type));
|
||||
std::memcpy(buff + (unsigned int) strlen(magic) + sizeof(payload_len) + sizeof(payload_type), msg, payload_len);
|
||||
}
|
||||
|
||||
explicit swaymsg(const unsigned int payloadType) : swaymsg(payloadType, nullptr) {}
|
||||
|
||||
[[nodiscard]] static swaymsg fromSock(const int sockfd) {
|
||||
char buff[6];
|
||||
size_t dlen;
|
||||
if ((dlen = recv(sockfd, buff, 6, 0)) != 6) {
|
||||
throw std::runtime_error(
|
||||
Formatter() << "Swaysock: Unexpected length on recv() call for magic: " << dlen
|
||||
>> Formatter::to_str);
|
||||
}
|
||||
|
||||
if (strncmp(buff, magic, 6) != 0) {
|
||||
throw std::runtime_error("Swaysock: magic did not match");
|
||||
}
|
||||
|
||||
unsigned int payloadType;
|
||||
unsigned int payloadLen;
|
||||
static_assert(sizeof(payloadType) == 4);
|
||||
static_assert(sizeof(payloadLen) == 4);
|
||||
|
||||
if ((dlen = recv(sockfd, &payloadLen, sizeof(payloadLen), 0)) != sizeof(payloadLen)) {
|
||||
throw std::runtime_error(
|
||||
Formatter() << "Swaysock: Unexpected length on recv() call for len: " << dlen >> Formatter::to_str);
|
||||
}
|
||||
|
||||
if ((dlen = recv(sockfd, &payloadType, sizeof(payloadType), 0)) != sizeof(payloadType)) {
|
||||
throw std::runtime_error(
|
||||
Formatter() << "Swaysock: Unexpected length on recv() call for type: " << dlen
|
||||
>> Formatter::to_str);
|
||||
}
|
||||
|
||||
char msgBuff[payloadLen];
|
||||
if ((dlen = recv(sockfd, msgBuff, payloadLen, 0)) != payloadLen) {
|
||||
throw std::runtime_error(
|
||||
Formatter() << "Swaysock: Unexpected length on recv() call for message: " << dlen
|
||||
>> Formatter::to_str);
|
||||
}
|
||||
return swaymsg(payloadType, msgBuff, payloadLen);
|
||||
};
|
||||
|
||||
constexpr const static char *magic = "i3-ipc";
|
||||
const unsigned int payload_len;
|
||||
const unsigned int payload_type;
|
||||
char *msg;
|
||||
unsigned char *buff = nullptr;
|
||||
|
||||
static_assert(sizeof(payload_len) == 4);
|
||||
static_assert(sizeof(payload_type) == 4);
|
||||
|
||||
[[nodiscard]] size_t size() const {
|
||||
return (int) strlen(magic) + sizeof(payload_len) + sizeof(payload_type) + payload_len;
|
||||
}
|
||||
|
||||
[[nodiscard]] void *asBuffer() const {
|
||||
return buff;
|
||||
}
|
||||
|
||||
~swaymsg() {
|
||||
delete buff;
|
||||
delete msg;
|
||||
}
|
||||
};
|
||||
|
||||
static const swaymsg SWAY_EXIT = swaymsg(0, "exit");
|
||||
static const swaymsg SWAY_GET_WORKSPACES = swaymsg(1);
|
||||
static const swaymsg SWAY_GET_OUTPUTS = swaymsg(3);
|
||||
static const swaymsg SWAY_GET_TREE = swaymsg(4);
|
||||
static const swaymsg SWAY_GET_VERSION = swaymsg(7);
|
||||
static const swaymsg SWAY_GET_CONFIG = swaymsg(9);
|
||||
static const swaymsg SWAY_GET_INPUTS = swaymsg(100);
|
||||
|
||||
|
||||
#endif //IPCSWAYTEST_SWAYMSG_H
|
91
tree/AbstractTreeModel.h
Normal file
91
tree/AbstractTreeModel.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
//
|
||||
// Created by grimmauld on 03.03.24.
|
||||
//
|
||||
|
||||
#ifndef SWAYMUX_ABSTRACTTREEMODEL_H
|
||||
#define SWAYMUX_ABSTRACTTREEMODEL_H
|
||||
|
||||
#include <type_traits>
|
||||
#include "AbstractTreeNode.h"
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
template<class T>
|
||||
class AbstractTreeModel : public QAbstractItemModel {
|
||||
static_assert(std::is_base_of<AbstractTreeNode<T>, T>::value,
|
||||
"Tree model subject class is not derived from AbstractTreeNode");
|
||||
|
||||
public:
|
||||
Q_DISABLE_COPY_MOVE(AbstractTreeModel)
|
||||
|
||||
explicit AbstractTreeModel(QObject *parent = nullptr): QAbstractItemModel(parent) {};
|
||||
|
||||
~AbstractTreeModel() override = default;
|
||||
|
||||
[[nodiscard]] QVariant data(const QModelIndex &index, int role) const override {
|
||||
if (!index.isValid() || role != Qt::DisplayRole)
|
||||
return {};
|
||||
|
||||
const auto *item = static_cast<const T *>(index.internalPointer());
|
||||
return item->data(index.column());
|
||||
}
|
||||
|
||||
[[nodiscard]] Qt::ItemFlags flags(const QModelIndex &index) const override {
|
||||
return index.isValid()
|
||||
? QAbstractItemModel::flags(index) : Qt::ItemFlags(Qt::NoItemFlags);
|
||||
}
|
||||
|
||||
[[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const override {
|
||||
if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
|
||||
return QVariant{};
|
||||
|
||||
return T{}.headerData(section);
|
||||
}
|
||||
|
||||
[[nodiscard]] QModelIndex index(int row, int column,
|
||||
const QModelIndex &parent = {}) const override {
|
||||
if (!hasIndex(row, column, parent))
|
||||
return {};
|
||||
|
||||
const T *parentItem = parent.isValid()
|
||||
? static_cast<T *>(parent.internalPointer())
|
||||
: getRoot();
|
||||
|
||||
if (auto *childItem = parentItem->child(row))
|
||||
return createIndex(row, column, childItem);
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]] QModelIndex parent(const QModelIndex &index) const override {
|
||||
if (!index.isValid())
|
||||
return {};
|
||||
|
||||
auto *childItem = static_cast<T *>(index.internalPointer());
|
||||
T *parentItem = childItem->parentItem();
|
||||
|
||||
return parentItem != getRoot()
|
||||
? createIndex(parentItem->row(), 0, parentItem) : QModelIndex{};
|
||||
}
|
||||
|
||||
[[nodiscard]] int rowCount(const QModelIndex &parent = {}) const override {
|
||||
if (parent.column() > 0)
|
||||
return 0;
|
||||
|
||||
const T *parentItem = parent.isValid()
|
||||
? static_cast<const T *>(parent.internalPointer())
|
||||
: getRoot();
|
||||
|
||||
return parentItem->childCount();
|
||||
}
|
||||
|
||||
[[nodiscard]] int columnCount(const QModelIndex &parent = {}) const override {
|
||||
if (parent.isValid())
|
||||
return static_cast<T *>(parent.internalPointer())->columnCount();
|
||||
return T{}.columnCount();
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual const T* getRoot() const = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif //SWAYMUX_ABSTRACTTREEMODEL_H
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
template<class T>
|
||||
class AbstractTreeNode {
|
||||
// static_assert(std::is_base_of<AbstractTreeNode, T>::value, "Derived not derived from BaseClass");
|
||||
public:
|
||||
std::vector<std::unique_ptr<T>> children{};
|
||||
|
||||
|
|
|
@ -4,76 +4,17 @@
|
|||
|
||||
#include "PsTreeModel.h"
|
||||
|
||||
PsTreeModel::PsTreeModel(QObject *parent) : QAbstractItemModel(parent), rootItem(get_process_records()) {}
|
||||
|
||||
QModelIndex PsTreeModel::index(int row, int column, const QModelIndex &parent) const {
|
||||
if (!hasIndex(row, column, parent))
|
||||
return {};
|
||||
|
||||
const ProcessTreeNode *parentItem = parent.isValid()
|
||||
? static_cast<ProcessTreeNode *>(parent.internalPointer())
|
||||
: &rootItem;
|
||||
|
||||
if (auto *childItem = parentItem->child(row))
|
||||
return createIndex(row, column, childItem);
|
||||
return {};
|
||||
}
|
||||
|
||||
QModelIndex PsTreeModel::parent(const QModelIndex &index) const {
|
||||
if (!index.isValid())
|
||||
return {};
|
||||
|
||||
auto *childItem = static_cast<ProcessTreeNode *>(index.internalPointer());
|
||||
ProcessTreeNode *parentItem = childItem->parentItem();
|
||||
|
||||
return parentItem != &rootItem
|
||||
? createIndex(parentItem->row(), 0, parentItem) : QModelIndex{};
|
||||
}
|
||||
|
||||
int PsTreeModel::rowCount(const QModelIndex &parent) const {
|
||||
if (parent.column() > 0)
|
||||
return 0;
|
||||
|
||||
const ProcessTreeNode *parentItem = parent.isValid()
|
||||
? static_cast<const ProcessTreeNode *>(parent.internalPointer())
|
||||
: &rootItem;
|
||||
|
||||
return parentItem->childCount();
|
||||
}
|
||||
|
||||
int PsTreeModel::columnCount(const QModelIndex &parent) const {
|
||||
if (parent.isValid())
|
||||
return static_cast<ProcessTreeNode *>(parent.internalPointer())->columnCount();
|
||||
return ProcessTreeNode{}.columnCount();
|
||||
}
|
||||
|
||||
QVariant PsTreeModel::data(const QModelIndex &index, int role) const {
|
||||
if (!index.isValid() || role != Qt::DisplayRole)
|
||||
return {};
|
||||
|
||||
const auto *item = static_cast<const ProcessTreeNode *>(index.internalPointer());
|
||||
return item->data(index.column());
|
||||
}
|
||||
|
||||
Qt::ItemFlags PsTreeModel::flags(const QModelIndex &index) const {
|
||||
return index.isValid()
|
||||
? QAbstractItemModel::flags(index) : Qt::ItemFlags(Qt::NoItemFlags);
|
||||
}
|
||||
|
||||
QVariant PsTreeModel::headerData(int section, Qt::Orientation orientation,
|
||||
int role) const {
|
||||
if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
|
||||
return QVariant{};
|
||||
|
||||
return ProcessTreeNode{}.headerData(section);
|
||||
}
|
||||
|
||||
void PsTreeModel::update() {
|
||||
auto changes = update_process_records(&rootItem);
|
||||
/*
|
||||
auto* root = getRoot();
|
||||
auto changes = update_process_records(root);
|
||||
|
||||
QList<QPersistentModelIndex> changedParents{};
|
||||
for(auto* node: changes) {
|
||||
changedParents.push_back(createIndex(node->row(), 0, node));
|
||||
}
|
||||
layoutAboutToBeChanged(changedParents);
|
||||
*/
|
||||
}
|
||||
|
||||
PsTreeModel::PsTreeModel(QObject *parent) : PsTreeModel(get_process_records(), parent) {}
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
|
||||
#include <QAbstractItemModel>
|
||||
#include "pstree.h"
|
||||
#include "AbstractTreeModel.h"
|
||||
|
||||
class PsTreeModel : public QAbstractItemModel {
|
||||
class PsTreeModel : public AbstractTreeModel<ProcessTreeNode> {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Q_DISABLE_COPY_MOVE(PsTreeModel)
|
||||
|
||||
|
@ -19,26 +19,16 @@ public:
|
|||
|
||||
~PsTreeModel() override = default;
|
||||
|
||||
[[nodiscard]] QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
[[nodiscard]] Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
[[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const override;
|
||||
|
||||
[[nodiscard]] QModelIndex index(int row, int column,
|
||||
const QModelIndex &parent = {}) const override;
|
||||
|
||||
[[nodiscard]] QModelIndex parent(const QModelIndex &index) const override;
|
||||
|
||||
[[nodiscard]] int rowCount(const QModelIndex &parent = {}) const override;
|
||||
|
||||
[[nodiscard]] int columnCount(const QModelIndex &parent = {}) const override;
|
||||
explicit PsTreeModel(ProcessTreeNode * rootItem, QObject *parent = nullptr) : rootItem(rootItem), AbstractTreeModel<ProcessTreeNode>(parent) {};
|
||||
|
||||
void update();
|
||||
|
||||
[[nodiscard]] const ProcessTreeNode *getRoot() const override {
|
||||
return rootItem;
|
||||
};
|
||||
|
||||
private:
|
||||
ProcessTreeNode rootItem;
|
||||
const ProcessTreeNode* rootItem;
|
||||
};
|
||||
|
||||
|
||||
|
|
5
tree/SwayTreeModel.cpp
Normal file
5
tree/SwayTreeModel.cpp
Normal file
|
@ -0,0 +1,5 @@
|
|||
//
|
||||
// Created by grimmauld on 03.03.24.
|
||||
//
|
||||
|
||||
#include "SwayTreeModel.h"
|
49
tree/SwayTreeModel.h
Normal file
49
tree/SwayTreeModel.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// Created by grimmauld on 03.03.24.
|
||||
//
|
||||
|
||||
#ifndef SWAYMUX_SWAYTREEMODEL_H
|
||||
#define SWAYMUX_SWAYTREEMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <utility>
|
||||
#include "pstree.h"
|
||||
#include "AbstractTreeModel.h"
|
||||
#include "swaytree.h"
|
||||
#include "../sway_bindings/Sway.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <utility>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
class SwayTreeModel : public AbstractTreeModel<SwayTreeNode> {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
inline static Sway sway = Sway();
|
||||
|
||||
Q_DISABLE_COPY_MOVE(SwayTreeModel)
|
||||
|
||||
explicit SwayTreeModel(QObject *parent = nullptr) : AbstractTreeModel<SwayTreeNode>(parent) {
|
||||
auto res = sway.sendIPC(SWAY_GET_TREE);
|
||||
auto rep = json::parse(res.msg);
|
||||
rootItem = new SwayTreeNode(rep);
|
||||
}
|
||||
|
||||
~SwayTreeModel() override = default;
|
||||
|
||||
explicit SwayTreeModel(SwayTreeNode * rootItem, QObject *parent = nullptr) : rootItem(rootItem),
|
||||
AbstractTreeModel<SwayTreeNode>(
|
||||
parent) {};
|
||||
|
||||
[[nodiscard]] const SwayTreeNode *getRoot() const override {
|
||||
return rootItem;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
SwayTreeNode * rootItem;
|
||||
};
|
||||
|
||||
#endif //SWAYMUX_SWAYTREEMODEL_H
|
|
@ -48,9 +48,9 @@ void populateTree(ProcessTreeNode *node, std::map<pid_t, std::set<ProcessRecord>
|
|||
}
|
||||
}
|
||||
|
||||
ProcessTreeNode get_process_records() {
|
||||
ProcessTreeNode root = ProcessTreeNode(); // rootPrc
|
||||
update_process_records(&root);
|
||||
ProcessTreeNode * get_process_records() {
|
||||
auto* root = new ProcessTreeNode(); // rootPrc
|
||||
update_process_records(root);
|
||||
return root;
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,9 @@ void printTree(const ProcessTreeNode &node, const std::string &prefix) {
|
|||
}
|
||||
|
||||
void printTree() {
|
||||
printTree(get_process_records(), "");
|
||||
auto* tree = get_process_records();
|
||||
printTree(*tree, "");
|
||||
delete tree;
|
||||
}
|
||||
|
||||
QVariant ProcessTreeNode::data(int column) const {
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
|
||||
ProcessRecord(std::string name, pid_t pid, pid_t ppid) : name(std::move(name)), pid(pid), ppid(ppid) {}
|
||||
|
||||
ProcessRecord() : name("root"), pid(0), ppid(-1) {}
|
||||
ProcessRecord() : name("rootItem"), pid(0), ppid(-1) {}
|
||||
|
||||
[[nodiscard]] bool operator<(const ProcessRecord &other) const {
|
||||
return this->pid < other.pid;
|
||||
|
@ -43,6 +43,9 @@ public:
|
|||
|
||||
class ProcessTreeNode : public AbstractTreeNode<ProcessTreeNode> {
|
||||
public:
|
||||
ProcessTreeNode(ProcessTreeNode& node) = delete; // default constructor to make the static asserts shut up
|
||||
ProcessTreeNode(const ProcessTreeNode& node) = delete; // default constructor to make the static asserts shut up
|
||||
|
||||
explicit ProcessTreeNode(ProcessTreeNode *parent = nullptr) : proc(ProcessRecord()), AbstractTreeNode(parent) {}
|
||||
|
||||
const ProcessRecord proc;
|
||||
|
@ -67,7 +70,7 @@ public:
|
|||
};
|
||||
};
|
||||
|
||||
ProcessTreeNode get_process_records();
|
||||
ProcessTreeNode * get_process_records();
|
||||
|
||||
void insert_process_record(const std::filesystem::path &status_path, std::map<pid_t, ProcessRecord> &buff);
|
||||
|
||||
|
|
14
tree/swaytree.cpp
Normal file
14
tree/swaytree.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
//
|
||||
// Created by grimmauld on 03.03.24.
|
||||
//
|
||||
|
||||
#include "swaytree.h"
|
||||
|
||||
QVariant SwayTreeNode::data(int column) const {
|
||||
// TODO: maybe add a more elaborate representation
|
||||
return QString::fromStdString(node.name);
|
||||
}
|
||||
|
||||
QVariant SwayTreeNode::headerData(int column) const {
|
||||
return "Title";
|
||||
}
|
155
tree/swaytree.h
Normal file
155
tree/swaytree.h
Normal file
|
@ -0,0 +1,155 @@
|
|||
//
|
||||
// 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"
|
||||
|
||||
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(rep["name"]),
|
||||
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; };
|
||||
};
|
||||
|
||||
|
||||
#endif //SWAYMUX_SWAYTREE_H
|
Loading…
Reference in a new issue