Add new functions
- move to scratch - restore (move selected to new workspace) - close
This commit is contained in:
parent
293a12d0b7
commit
f3b60a4a2a
10 changed files with 255 additions and 35 deletions
|
@ -43,6 +43,10 @@ set(PROJECT_SOURCES
|
|||
Keys/JumpOutputKeyListener.h
|
||||
Keys/PrevOutputKeyListener.h
|
||||
Keys/NextOutputKeyListener.h
|
||||
Keys/CloseKeyListener.h
|
||||
Keys/MoveToScratchpadKeyListener.h
|
||||
Keys/MoveToScratchpadKeyListener.h
|
||||
Keys/RestoreKeyListener.h
|
||||
)
|
||||
|
||||
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
|
|
58
Keys/CloseKeyListener.h
Normal file
58
Keys/CloseKeyListener.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
//
|
||||
// Created by grimmauld on 11.03.24.
|
||||
//
|
||||
|
||||
#ifndef SWAYMUX_CLOSEKEYLISTENER_H
|
||||
#define SWAYMUX_CLOSEKEYLISTENER_H
|
||||
|
||||
|
||||
#include "AbstractKeyListener.h"
|
||||
|
||||
class CloseKeyListener : public AbstractKeyListener {
|
||||
public:
|
||||
explicit CloseKeyListener(MainWindow *pWindow) : window(pWindow) {}
|
||||
|
||||
void handleKeyEvent(const QKeyEvent *keyEvent) const override {
|
||||
auto selectedNodes = window->model->getSelectedNodes(window->ui->treeView);
|
||||
|
||||
std::set<int> containersToKill;
|
||||
for (auto* container: selectedNodes) {
|
||||
auto containers = container->accumulateContainers();
|
||||
for (auto* containerToMove : container->accumulateContainers()) {
|
||||
containersToKill.insert(containerToMove->node.id);
|
||||
}
|
||||
}
|
||||
|
||||
if (containersToKill.empty())
|
||||
return;
|
||||
|
||||
Formatter cmd;
|
||||
for (auto id: containersToKill) {
|
||||
cmd << "[con_id=" << id << "] kill ; ";
|
||||
}
|
||||
|
||||
std::cout << cmd.str() << "\n";
|
||||
auto resp = SwayTreeModel::sway.sendIPC(swaymsg(0, cmd.str()));
|
||||
std::cout << resp.msg << "\n";
|
||||
|
||||
usleep(100000); // give sway time to react. Not great but works i guess.
|
||||
window->updateModel();
|
||||
}
|
||||
|
||||
std::string getDescription() override {
|
||||
return "Close selected windows";
|
||||
}
|
||||
|
||||
std::string getKeyText() override {
|
||||
return "Q / DEL";
|
||||
}
|
||||
|
||||
[[nodiscard]] bool canAcceptKey(int key) const override {
|
||||
return key == Qt::Key_Q || key == Qt::Key_Delete;
|
||||
}
|
||||
private:
|
||||
MainWindow *window;
|
||||
};
|
||||
|
||||
|
||||
#endif //SWAYMUX_CLOSEKEYLISTENER_H
|
61
Keys/MoveToScratchpadKeyListener.h
Normal file
61
Keys/MoveToScratchpadKeyListener.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// Created by grimmauld on 11.03.24.
|
||||
//
|
||||
|
||||
#ifndef SWAYMUX_MOVETOSCRATCHPADKEYLISTENER_H
|
||||
#define SWAYMUX_MOVETOSCRATCHPADKEYLISTENER_H
|
||||
|
||||
|
||||
#include "AbstractKeyListener.h"
|
||||
#include "../mainwindow.h"
|
||||
#include "../sway_bindings/Formatter.h"
|
||||
#include "../tree/SwayTreeModel.h"
|
||||
|
||||
class MoveToScratchpadKeyListener : public AbstractKeyListener {
|
||||
public:
|
||||
explicit MoveToScratchpadKeyListener(MainWindow *pWindow) : window(pWindow) {}
|
||||
|
||||
void handleKeyEvent(const QKeyEvent *keyEvent) const override {
|
||||
auto selectedNodes = window->model->getSelectedNodes(window->ui->treeView);
|
||||
|
||||
std::set<int> containersToScratch;
|
||||
for (auto* container: selectedNodes) {
|
||||
auto containers = container->accumulateContainers();
|
||||
for (auto* containerToMove : container->accumulateContainers()) {
|
||||
containersToScratch.insert(containerToMove->node.id);
|
||||
}
|
||||
}
|
||||
|
||||
if (containersToScratch.empty())
|
||||
return;
|
||||
|
||||
Formatter cmd;
|
||||
for (auto id: containersToScratch) {
|
||||
cmd << "[con_id=" << id << "] move scratchpad ; ";
|
||||
}
|
||||
|
||||
std::cout << cmd.str() << "\n";
|
||||
auto resp = SwayTreeModel::sway.sendIPC(swaymsg(0, cmd.str()));
|
||||
std::cout << resp.msg << "\n";
|
||||
|
||||
usleep(100000); // give sway time to react. Not great but works i guess.
|
||||
window->updateModel();
|
||||
}
|
||||
|
||||
std::string getDescription() override {
|
||||
return "Move selected windows to scratchpad";
|
||||
}
|
||||
|
||||
std::string getKeyText() override {
|
||||
return "-";
|
||||
}
|
||||
|
||||
[[nodiscard]] bool canAcceptKey(int key) const override {
|
||||
return key == Qt::Key_Minus;
|
||||
}
|
||||
private:
|
||||
MainWindow *window;
|
||||
};
|
||||
|
||||
|
||||
#endif //SWAYMUX_MOVETOSCRATCHPADKEYLISTENER_H
|
65
Keys/RestoreKeyListener.h
Normal file
65
Keys/RestoreKeyListener.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
//
|
||||
// Created by grimmauld on 11.03.24.
|
||||
//
|
||||
|
||||
#ifndef SWAYMUX_RESTOREKEYLISTENER_H
|
||||
#define SWAYMUX_RESTOREKEYLISTENER_H
|
||||
|
||||
|
||||
#include "AbstractKeyListener.h"
|
||||
#include "../mainwindow.h"
|
||||
#include "../sway_bindings/Formatter.h"
|
||||
#include "../tree/SwayTreeModel.h"
|
||||
|
||||
class RestoreKeyListener : public AbstractKeyListener {
|
||||
public:
|
||||
explicit RestoreKeyListener(MainWindow *pWindow) : window(pWindow) {}
|
||||
|
||||
void handleKeyEvent(const QKeyEvent *keyEvent) const override {
|
||||
auto selectedNodes = window->model->getSelectedNodes(window->ui->treeView);
|
||||
|
||||
std::set<int> containersToScratch;
|
||||
for (auto* container: selectedNodes) {
|
||||
auto containers = container->accumulateContainers();
|
||||
for (auto* containerToMove : container->accumulateContainers()) {
|
||||
containersToScratch.insert(containerToMove->node.id);
|
||||
}
|
||||
}
|
||||
|
||||
if (containersToScratch.empty())
|
||||
return;
|
||||
|
||||
Formatter cmd;
|
||||
auto used_workspaces = window->model->getRoot()->accumulateWorkspaces();
|
||||
int i = 1; // workspace 1 is the first one. We don't expect our users to be programmers.
|
||||
for (; used_workspaces.contains(std::to_string(i)); ++i) {}
|
||||
|
||||
for (auto id: containersToScratch) {
|
||||
cmd << "[con_id=" << id << "] move workspace " << i << " ; ";
|
||||
}
|
||||
|
||||
std::cout << cmd.str() << "\n";
|
||||
auto resp = SwayTreeModel::sway.sendIPC(swaymsg(0, cmd.str()));
|
||||
std::cout << resp.msg << "\n";
|
||||
|
||||
usleep(100000); // give sway time to react. Not great but works i guess.
|
||||
window->updateModel();
|
||||
}
|
||||
|
||||
std::string getDescription() override {
|
||||
return "Restore selected windows to a new workspace";
|
||||
}
|
||||
|
||||
std::string getKeyText() override {
|
||||
return "+";
|
||||
}
|
||||
|
||||
[[nodiscard]] bool canAcceptKey(int key) const override {
|
||||
return key == Qt::Key_Plus;
|
||||
}
|
||||
private:
|
||||
MainWindow *window;
|
||||
};
|
||||
|
||||
|
||||
#endif //SWAYMUX_RESTOREKEYLISTENER_H
|
|
@ -69,7 +69,7 @@ public:
|
|||
return;
|
||||
|
||||
for (auto id: containersToMove) {
|
||||
cmd << "[con_id=" << id << "] focus , move container workspace " << newWorkspace << " ; ";
|
||||
cmd << "[con_id=" << id << "] move container workspace " << newWorkspace << " ; ";
|
||||
}
|
||||
|
||||
cmd << "workspace number " << newWorkspace;
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
#include "Keys/SwitchToKeybindListener.h"
|
||||
#include "Keys/PrevOutputKeyListener.h"
|
||||
#include "Keys/NextOutputKeyListener.h"
|
||||
#include "Keys/NextOutputKeyListener.h"
|
||||
#include "Keys/CloseKeyListener.h"
|
||||
#include "Keys/MoveToScratchpadKeyListener.h"
|
||||
#include "Keys/RestoreKeyListener.h"
|
||||
#include <QTimer>
|
||||
#include <iostream>
|
||||
|
||||
|
@ -18,19 +20,9 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
ui->setupUi(this);
|
||||
|
||||
model = new SwayTreeModel(ui->treeView);
|
||||
// modelUpdateTimer = new QTimer(this);
|
||||
// connect(modelUpdateTimer, &QTimer::timeout, this, QOverload<>::of(&MainWindow::update));
|
||||
// modelUpdateTimer->start(1000);
|
||||
|
||||
ui->statusbar->showMessage(QString::fromStdString("Press ? for keybind listing"));
|
||||
ui->treeView->setModel(model);
|
||||
ui->treeView->expandAll();
|
||||
|
||||
ui->treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
ui->treeView->selectionModel()->setCurrentIndex(model->findFocusedWindowIndex(), QItemSelectionModel::ClearAndSelect);
|
||||
|
||||
for (int c = 0; c < model->columnCount(); ++c)
|
||||
ui->treeView->resizeColumnToContents(c);
|
||||
updateModel();
|
||||
|
||||
swayTreeKeyHandler = new KeyHandler();
|
||||
swayTreeKeyHandler->addListener(new HelpKeyListener(ui->help_page));
|
||||
|
@ -39,6 +31,9 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
swayTreeKeyHandler->addListener(new SwitchToKeybindListener(model, ui->treeView));
|
||||
swayTreeKeyHandler->addListener(new PrevOutputKeyListener(model, ui->treeView));
|
||||
swayTreeKeyHandler->addListener(new NextOutputKeyListener(model, ui->treeView));
|
||||
swayTreeKeyHandler->addListener(new CloseKeyListener(this));
|
||||
swayTreeKeyHandler->addListener(new MoveToScratchpadKeyListener(this));
|
||||
swayTreeKeyHandler->addListener(new RestoreKeyListener(this));
|
||||
|
||||
closeHelpKeyHandler = new KeyHandler(ui->tree_page);
|
||||
closeHelpKeyHandler->addListener(new CloseHelpKeyListener(ui->tree_page));
|
||||
|
@ -58,8 +53,25 @@ MainWindow::~MainWindow() {
|
|||
delete closeHelpKeyHandler;
|
||||
}
|
||||
|
||||
void MainWindow::keyPressEvent(QKeyEvent *event) {
|
||||
if (event->key() == Qt::Key_W) {
|
||||
qDebug() << "hi";
|
||||
}
|
||||
}
|
||||
void MainWindow::updateModel() const {
|
||||
ui->treeView->setModel(nullptr);
|
||||
auto *focused = model->getRoot() == nullptr ? nullptr : model->getRoot()->findFocused();
|
||||
int id;
|
||||
if (focused != nullptr)
|
||||
id = focused->node.id;
|
||||
|
||||
model->generateRoot();
|
||||
if (focused == nullptr)
|
||||
focused = model->getRoot()->findFocused();
|
||||
else
|
||||
focused = model->getRoot()->findById(id);
|
||||
|
||||
if (focused != nullptr)
|
||||
focused->node.focused = true;
|
||||
|
||||
ui->treeView->setModel(model);
|
||||
ui->treeView->expandAll();
|
||||
ui->treeView->selectionModel()->setCurrentIndex(model->findIndexByNode(focused), QItemSelectionModel::ClearAndSelect);
|
||||
for (int c = 0; c < model->columnCount(); ++c)
|
||||
ui->treeView->resizeColumnToContents(c);
|
||||
}
|
||||
|
|
|
@ -20,11 +20,12 @@ public:
|
|||
explicit MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow() override;
|
||||
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
void updateModel() const;
|
||||
|
||||
SwayTreeModel* model;
|
||||
Ui::MainWindow *ui;
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
SwayTreeModel* model;
|
||||
// QTimer* modelUpdateTimer{};
|
||||
KeyHandler* swayTreeKeyHandler;
|
||||
KeyHandler* closeHelpKeyHandler;
|
||||
|
|
|
@ -72,13 +72,13 @@ public:
|
|||
return matching;
|
||||
}
|
||||
|
||||
[[nodiscard]] const T *findChildRecursive(std::function<bool(const T *)> test) const {
|
||||
if (test((const T *) this))
|
||||
return (const T*) this;
|
||||
[[nodiscard]] T *findChildRecursive(std::function<bool(const T *)> test) {
|
||||
if (test((T *) this))
|
||||
return (T*) this;
|
||||
|
||||
for (int i = 0; i < childCount(); ++i) {
|
||||
auto *c = child(i);
|
||||
const T *r = c->findChildRecursive(test);
|
||||
T *r = c->findChildRecursive(test);
|
||||
if (r != nullptr)
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,10 @@ public:
|
|||
Q_DISABLE_COPY_MOVE(SwayTreeModel)
|
||||
|
||||
explicit SwayTreeModel(QObject *parent = nullptr) : AbstractTreeModel<SwayTreeNode>(parent) {
|
||||
rootItem = nullptr;
|
||||
}
|
||||
|
||||
void generateRoot() {
|
||||
auto res = sway.sendIPC(SWAY_GET_TREE);
|
||||
auto rep = json::parse(res.msg);
|
||||
rootItem = new SwayTreeNode(rep);
|
||||
|
@ -34,11 +38,11 @@ public:
|
|||
|
||||
~SwayTreeModel() override = default;
|
||||
|
||||
explicit SwayTreeModel(SwayTreeNode * rootItem, QObject *parent = nullptr) : rootItem(rootItem),
|
||||
AbstractTreeModel<SwayTreeNode>(
|
||||
parent) {};
|
||||
explicit SwayTreeModel(SwayTreeNode *rootItem, QObject *parent = nullptr) : rootItem(rootItem),
|
||||
AbstractTreeModel<SwayTreeNode>(
|
||||
parent) {};
|
||||
|
||||
[[nodiscard]] const SwayTreeNode *getRoot() const override {
|
||||
[[nodiscard]] SwayTreeNode *getRoot() const override {
|
||||
return rootItem;
|
||||
};
|
||||
|
||||
|
@ -47,14 +51,15 @@ public:
|
|||
return findIndexByNode(getRoot()->findFocused());
|
||||
}
|
||||
|
||||
[[nodiscard]] std::set<SwayTreeNode*> getSelectedNodes(const QTreeView* treeView) const;
|
||||
[[nodiscard]] std::set<SwayTreeNode *> getSelectedNodes(const QTreeView *treeView) const;
|
||||
|
||||
[[nodiscard]] SwayTreeNode * getSelectedNode(const QModelIndex &i) const;
|
||||
[[nodiscard]] SwayTreeNode *getSelectedNode(const QModelIndex &i) const;
|
||||
|
||||
[[nodiscard]] QModelIndex findIndexByNode(const SwayTreeNode *node) const;
|
||||
|
||||
|
||||
private:
|
||||
SwayTreeNode * rootItem;
|
||||
SwayTreeNode *rootItem;
|
||||
};
|
||||
|
||||
#endif //SWAYMUX_SWAYTREEMODEL_H
|
||||
|
|
|
@ -106,7 +106,7 @@ struct SwayRecord {
|
|||
const NodeOrientation::NodeOrientation orientation;
|
||||
const bool urgent;
|
||||
const bool sticky;
|
||||
const bool focused;
|
||||
bool focused;
|
||||
|
||||
[[nodiscard]] bool operator<(const SwayRecord &other) const {
|
||||
return this->id < other.id;
|
||||
|
@ -130,16 +130,20 @@ private:
|
|||
|
||||
class SwayTreeNode : public AbstractTreeNode<SwayTreeNode> {
|
||||
public:
|
||||
const SwayRecord node;
|
||||
SwayRecord node;
|
||||
|
||||
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;
|
||||
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;
|
||||
auto childNode = std::make_unique<SwayTreeNode>(child, this);
|
||||
this->appendChild(childNode);
|
||||
}
|
||||
|
@ -160,7 +164,7 @@ public:
|
|||
|
||||
[[nodiscard]] int columnCount() const override { return 1; };
|
||||
|
||||
[[nodiscard]] const SwayTreeNode *findFocused() const {
|
||||
[[nodiscard]] SwayTreeNode *findFocused() {
|
||||
std::function<bool(const SwayTreeNode *)> focused = [](const SwayTreeNode *testNode) {
|
||||
return testNode->node.focused;
|
||||
};
|
||||
|
@ -191,6 +195,12 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
[[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});
|
||||
|
@ -204,6 +214,10 @@ private:
|
|||
});
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] bool operator==(const SwayTreeNode * other) const {
|
||||
return this->node == other->node;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue