Add per-tool settings and gesture customization

This commit is contained in:
ajp_anton
2026-09-05 05:02:34 +00:00
parent d6f30c5735
commit 38142b9499
26 changed files with 1383 additions and 83 deletions
+25 -3
View File
@@ -36,6 +36,23 @@ constexpr auto configFile = "plasma-org.kde.plasma.desktop-appletsrc";
constexpr auto componentId = "se.ajpanton.plasma-task-group-shortcuts";
constexpr auto stateFile = "plasma-task-group-shortcutsrc";
struct ShortcutSettings {
bool startWithFirst = true;
bool initialShiftOpensNewInstance = true;
bool shiftCyclesBackward = true;
};
ShortcutSettings shortcutSettings()
{
const auto config = KSharedConfig::openConfig(QString::fromLatin1(stateFile));
const KConfigGroup group(config, QStringLiteral("Settings"));
return {
group.readEntry("StartWithFirstWindow", true),
group.readEntry("InitialShiftOpensNewInstance", true),
group.readEntry("ShiftCyclesBackward", true),
};
}
KConfigGroup displacedShortcutGroup(int number)
{
const auto config = KSharedConfig::openConfig(QString::fromLatin1(stateFile));
@@ -282,15 +299,20 @@ private:
return;
}
const ShortcutSettings settings = shortcutSettings();
const bool continuing = row == m_lastShortcut;
if (!continuing) {
m_cyclePosition = 0;
const bool backwards = shifted
&& settings.shiftCyclesBackward
&& !settings.initialShiftOpensNewInstance;
m_cyclePosition = initialCyclePosition(
m_model, tasks.at(row), settings.startWithFirst, backwards);
} else {
m_cyclePosition += shifted ? -1 : 1;
m_cyclePosition += shifted && settings.shiftCyclesBackward ? -1 : 1;
}
m_lastShortcut = row;
if (shifted && !continuing) {
if (shifted && !continuing && settings.initialShiftOpensNewInstance) {
m_model.requestNewInstance(m_model.index(tasks.at(row), 0));
return;
}
@@ -1,7 +1,7 @@
Name: plasma-task-group-shortcuts
Version: 0.1.0
Release: 13%{?dist}
Summary: Application-group shortcuts for the Plasma Task Manager
Release: 15%{?dist}
Summary: Windows-like application-group shortcuts for the Plasma Task Manager
License: MIT
URL: https://git.ajpanton.se/ajp_anton/fedora-tools
@@ -54,6 +54,12 @@ install -Dpm 0644 %{SOURCE2} \
%{_sysconfdir}/xdg/autostart/se.ajpanton.plasma-task-group-shortcuts-autostart.desktop
%changelog
* Sat Sep 05 2026 fedora-tools contributors - 0.1.0-15
- Clarify the package summary
* Sat Sep 05 2026 fedora-tools contributors - 0.1.0-14
- Add configurable cycle start and Shift behavior
* Sat Sep 05 2026 fedora-tools contributors - 0.1.0-13
- Advertise the tool to Fedora Tools settings
@@ -72,3 +72,22 @@ QVector<int> logicalTaskRows(const QAbstractItemModel &model, bool separateLaunc
}
return rows;
}
int initialCyclePosition(const QAbstractItemModel &model, int row, bool startWithFirst, bool backwards)
{
const QModelIndex group = model.index(row, 0);
const int childCount = model.rowCount(group);
if (childCount == 0) {
return 0;
}
if (!startWithFirst) {
for (int child = 0; child < childCount; ++child) {
if (model.index(child, 0, group).data(AbstractTasksModel::IsActive).toBool()) {
return child + (backwards ? -1 : 1);
}
}
}
return backwards ? childCount - 1 : 0;
}
@@ -9,3 +9,4 @@ class QAbstractItemModel;
QModelIndex taskToActivate(const QAbstractItemModel &model, int row, int cyclePosition);
QVector<int> logicalTaskRows(const QAbstractItemModel &model, bool separateLaunchers);
int initialCyclePosition(const QAbstractItemModel &model, int row, bool startWithFirst, bool backwards);
@@ -17,6 +17,9 @@ private Q_SLOTS:
void returnsTopLevelTask();
void selectsChildByCyclePosition();
void startsWithFirstChild();
void startsWithLastChildWhenReversing();
void startsAfterActiveChild();
void startsBeforeActiveChildWhenReversing();
void keepsSeparateLaunchersAsSlots();
void mergesLauncherWithRunningApplication();
};
@@ -59,6 +62,45 @@ void TaskSelectionTest::startsWithFirstChild()
QCOMPARE(taskToActivate(model, 0, 0), model.index(0, 0, model.index(0, 0)));
}
void TaskSelectionTest::startsWithLastChildWhenReversing()
{
QStandardItemModel model;
auto *group = new QStandardItem(QStringLiteral("Dolphin"));
group->appendRow(new QStandardItem(QStringLiteral("one")));
group->appendRow(new QStandardItem(QStringLiteral("two")));
group->appendRow(new QStandardItem(QStringLiteral("three")));
model.appendRow(group);
QCOMPARE(initialCyclePosition(model, 0, true, true), 2);
}
void TaskSelectionTest::startsAfterActiveChild()
{
QStandardItemModel model;
auto *group = new QStandardItem(QStringLiteral("Firefox"));
group->appendRow(new QStandardItem(QStringLiteral("one")));
group->appendRow(new QStandardItem(QStringLiteral("two")));
group->appendRow(new QStandardItem(QStringLiteral("three")));
model.appendRow(group);
group->child(1)->setData(true, AbstractTasksModel::IsActive);
QCOMPARE(initialCyclePosition(model, 0, false, false), 2);
}
void TaskSelectionTest::startsBeforeActiveChildWhenReversing()
{
QStandardItemModel model;
auto *group = new QStandardItem(QStringLiteral("Firefox"));
group->appendRow(new QStandardItem(QStringLiteral("one")));
group->appendRow(new QStandardItem(QStringLiteral("two")));
group->appendRow(new QStandardItem(QStringLiteral("three")));
model.appendRow(group);
group->child(0)->setData(true, AbstractTasksModel::IsActive);
QCOMPARE(initialCyclePosition(model, 0, false, true), -1);
QCOMPARE(taskToActivate(model, 0, -1), model.index(2, 0, model.index(0, 0)));
}
void TaskSelectionTest::keepsSeparateLaunchersAsSlots()
{
QStandardItemModel model;