mirror of
https://github.com/Bismuth-Forge/bismuth.git
synced 2024-08-14 18:40:35 +03:00
feat: add KCM for Bismuth configuration
This commit is contained in:
parent
3000934a96
commit
1c410cf1c7
@ -35,3 +35,13 @@ METADATA_FILE="$KWINSCRIPT_BUILDDIR/metadata.desktop"
|
||||
cp "$KWINSCRIPT_SOURCEDIR/res/metadata.desktop" "$METADATA_FILE"
|
||||
sed -i "s/\$VER/${npm_package_version:-1.0}/" "$METADATA_FILE"
|
||||
|
||||
|
||||
echo "🏗️ Building KCM..."
|
||||
|
||||
KCM_SOURCEDIR="src/kcm"
|
||||
KCM_BUILDDIR="build/kcm"
|
||||
|
||||
cmake -S "$KCM_SOURCEDIR" -B "$KCM_BUILDDIR" -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||
cmake --build "$KCM_BUILDDIR"
|
||||
ln -sf "$PWD/$KCM_BUILDDIR/compile_commands.json" "$KCM_SOURCEDIR/compile_commands.json" # For LSP
|
||||
|
||||
|
@ -6,6 +6,13 @@
|
||||
set -e
|
||||
|
||||
echo "📦 Installing the KWin Script..."
|
||||
KWINPKG_FILE="bismuth.kwinscript"
|
||||
plasmapkg2 -u "$KWINPKG_FILE" > /dev/null || plasmapkg2 -i "$KWINPKG_FILE" > /dev/null
|
||||
|
||||
KWINSCRIPT_BUILDDIR="build/kwinscript"
|
||||
KWINPKG_FILE="bismuth.kwinscript"
|
||||
|
||||
plasmapkg2 -u "$KWINSCRIPT_BUILDDIR/$KWINPKG_FILE" > /dev/null || plasmapkg2 -i "$KWINSCRIPT_BUILDDIR/$KWINPKG_FILE" > /dev/null
|
||||
|
||||
echo "📦 Installing the KCM..."
|
||||
|
||||
KCM_BUILDDIR="build/kcm"
|
||||
sudo cmake --install "$KCM_BUILDDIR"
|
||||
|
@ -23,5 +23,3 @@ zip -qr "$KWINPKG_NAME" ./contents/ ./metadata.desktop
|
||||
# Get back to the original directory
|
||||
cd - > /dev/null
|
||||
|
||||
# TODO: Packaging for KCM
|
||||
|
||||
|
@ -9,5 +9,8 @@ set -e
|
||||
echo "🔥 Uninstalling KWin Script..."
|
||||
plasmapkg2 -t kwinscript -r "${npm_package_name:-Bismuth}"
|
||||
|
||||
# TODO: Uninstalling KCM
|
||||
echo "🔥 Uninstalling KCM..."
|
||||
KCM_BUILDDIR="build/kcm"
|
||||
|
||||
sudo xargs rm < "$KCM_BUILDDIR/install_manifest.txt"
|
||||
|
||||
|
58
src/kcm/CMakeLists.txt
Normal file
58
src/kcm/CMakeLists.txt
Normal file
@ -0,0 +1,58 @@
|
||||
# SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(bismuth-kcm)
|
||||
|
||||
set(QT_MIN_VERSION "5.15.0")
|
||||
set(KF5_MIN_VERSION "5.80.0")
|
||||
|
||||
find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE)
|
||||
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
|
||||
|
||||
include(KDEInstallDirs)
|
||||
include(KDECMakeSettings)
|
||||
include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE)
|
||||
|
||||
find_package(
|
||||
Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
|
||||
Quick
|
||||
Svg
|
||||
)
|
||||
|
||||
find_package(
|
||||
KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
|
||||
I18n
|
||||
KCMUtils
|
||||
Declarative
|
||||
Config
|
||||
)
|
||||
|
||||
add_library(kcm_bismuth MODULE)
|
||||
|
||||
target_sources(
|
||||
kcm_bismuth
|
||||
PRIVATE
|
||||
bismuth.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
kcm_bismuth
|
||||
PRIVATE
|
||||
Qt5::Core
|
||||
KF5::CoreAddons
|
||||
KF5::I18n
|
||||
KF5::QuickAddons
|
||||
KF5::ConfigCore
|
||||
KF5::ConfigGui
|
||||
)
|
||||
|
||||
kconfig_add_kcfg_files(kcm_bismuth GENERATE_MOC bismuth_config.kcfgc)
|
||||
kcoreaddons_desktop_to_json(kcm_bismuth "package/metadata.desktop")
|
||||
|
||||
install(FILES "bismuth_config.kcfg" DESTINATION ${KDE_INSTALL_KCFGDIR})
|
||||
install(TARGETS kcm_bismuth DESTINATION ${KDE_INSTALL_PLUGINDIR}/kcms)
|
||||
install(FILES package/metadata.desktop RENAME kcm_bismuth.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR})
|
||||
|
||||
kpackage_install_package(package kcm_bismuth kcms)
|
46
src/kcm/CMakePresets.json
Normal file
46
src/kcm/CMakePresets.json
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"version": 3,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 21,
|
||||
"patch": 0
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "default",
|
||||
"displayName": "Default Config",
|
||||
"description": "Default build using Ninja generator",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build/",
|
||||
"installDir": "~/.local/kde",
|
||||
"cacheVariables": {
|
||||
"CMAKE_EXPORT_COMPILE_COMMANDS": {
|
||||
"type": "BOOL",
|
||||
"value": "ON"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "release",
|
||||
"displayName": "Release Config",
|
||||
"description": "Release build using Ninja generator",
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build/release/",
|
||||
"installDir": "/usr",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "default",
|
||||
"configurePreset": "default"
|
||||
},
|
||||
{
|
||||
"name": "release",
|
||||
"configurePreset": "release",
|
||||
"configuration": "Release"
|
||||
}
|
||||
]
|
||||
}
|
3
src/kcm/CMakePresets.json.license
Normal file
3
src/kcm/CMakePresets.json.license
Normal file
@ -0,0 +1,3 @@
|
||||
SPDX-FileCopyrightText: none
|
||||
|
||||
SPDX-License-Identifier: MIT
|
68
src/kcm/CONTRIBUTING.md
Normal file
68
src/kcm/CONTRIBUTING.md
Normal file
@ -0,0 +1,68 @@
|
||||
<!-- SPDX-FileCopyrightText: none -->
|
||||
<!-- SPDX-License-Identifier: MIT -->
|
||||
|
||||
# 🤝 Contributing
|
||||
|
||||
We glad, that you want to contribute to the project. To make things easier please read the
|
||||
following.
|
||||
|
||||
## 🏗️ Development packages
|
||||
|
||||
To make sure you can develop the script install all the tools you need:
|
||||
|
||||
- [REUSE tool](https://git.fsfe.org/reuse/tool#install)
|
||||
- [CMake](https://cmake.org/) (3.21 or later)
|
||||
- [Pre-commit](https://pre-commit.com/)
|
||||
- [Clang-format](https://clang.llvm.org/docs/ClangFormat.html)
|
||||
|
||||
## 👷 Prepare environment
|
||||
|
||||
The command will install Git pre-commit hooks you will need, such as automatic
|
||||
REUSE validation and autoformatting.
|
||||
|
||||
```bash
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
Install the dependencies on your Linux Distribution:
|
||||
|
||||
```bash
|
||||
# Ubuntu
|
||||
sudo apt install -y \
|
||||
cmake ninja-build extra-cmake-modules kirigami2-dev \
|
||||
libkf5config-dev libkf5configwidgets-dev libkf5coreaddons-dev \
|
||||
libkf5declarative-dev libkf5i18n-dev libkf5kcmutils-dev \
|
||||
libqt5svg5-dev qml-module-qtquick* qtbase5-dev \
|
||||
qtdeclarative5-dev qtquickcontrols2-5-dev g++
|
||||
```
|
||||
|
||||
```bash
|
||||
# Fedora
|
||||
sudo dnf install -y \
|
||||
kf5-kconfigwidgets-devel qt5-qtbase-devel qt5-qtbase-private-devel \
|
||||
qt5-qtdeclarative-devel qt5-qtquickcontrols2-devel qt5-qtsvg-devel \
|
||||
qt5-qtfeedback-devel cmake ninja-build extra-cmake-modules \
|
||||
kf5-kcmutils-devel kf5-ki18n-devel kf5-kdeclarative-devel
|
||||
```
|
||||
|
||||
```bash
|
||||
# OpenSUSE
|
||||
sudo zypper --non-interactive install --recommends -t pattern devel_qt5 devel_C_C++
|
||||
sudo zypper --non-interactive in -y \
|
||||
ninja extra-cmake-modules kconfig-devel kcmutils-devel kdeclarative-devel \
|
||||
ki18n-devel
|
||||
```
|
||||
|
||||
## 🛠️ Building
|
||||
|
||||
```bash
|
||||
cmake --preset default
|
||||
cmake --build --preset default
|
||||
```
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
```bash
|
||||
source build/prefix.sh
|
||||
kcmshell5 kcm_bismuth
|
||||
```
|
42
src/kcm/bismuth.cpp
Normal file
42
src/kcm/bismuth.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "bismuth.h"
|
||||
#include "bismuth_config.h"
|
||||
|
||||
#include <KAboutData>
|
||||
#include <KLocalizedString>
|
||||
#include <KPluginFactory>
|
||||
|
||||
K_PLUGIN_CLASS_WITH_JSON(BismuthSettings, "metadata.json")
|
||||
|
||||
BismuthSettings::BismuthSettings(QObject *parent, const QVariantList &args)
|
||||
: KQuickAddons::ManagedConfigModule(parent, args)
|
||||
, m_config(new Bismuth::Config(this))
|
||||
{
|
||||
KAboutData *aboutData =
|
||||
new KAboutData(QStringLiteral("kcm_bismuth"),
|
||||
i18nc("@title", "Window Tiling"),
|
||||
QStringLiteral("1.0"),
|
||||
QStringLiteral(""),
|
||||
KAboutLicense::LicenseKey::Custom,
|
||||
i18nc("@info:credit", "Copyright 2021 Mikhail Zolotukhin <mail@genda.life>"));
|
||||
|
||||
aboutData->addAuthor(
|
||||
i18nc("@info:credit", "Author"), i18nc("@info:credit", "Author"), QStringLiteral("author@domain.com"));
|
||||
|
||||
setAboutData(aboutData);
|
||||
setButtons(Help | Apply | Default);
|
||||
|
||||
qmlRegisterAnonymousType<Bismuth::Config>("org.kde.bismuth.private", 1);
|
||||
}
|
||||
|
||||
Bismuth::Config *BismuthSettings::config() const
|
||||
{
|
||||
return m_config;
|
||||
}
|
||||
|
||||
#include "bismuth.moc"
|
26
src/kcm/bismuth.h
Normal file
26
src/kcm/bismuth.h
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <KQuickAddons/ManagedConfigModule>
|
||||
|
||||
#include "bismuth_config.h"
|
||||
|
||||
class BismuthSettings : public KQuickAddons::ManagedConfigModule
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(Bismuth::Config *config READ config CONSTANT)
|
||||
|
||||
public:
|
||||
BismuthSettings(QObject *parent, const QVariantList &args);
|
||||
virtual ~BismuthSettings() override = default;
|
||||
|
||||
Bismuth::Config *config() const;
|
||||
|
||||
private:
|
||||
Bismuth::Config *m_config;
|
||||
};
|
184
src/kcm/bismuth_config.kcfg
Normal file
184
src/kcm/bismuth_config.kcfg
Normal file
@ -0,0 +1,184 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life> -->
|
||||
<!-- SPDX-License-Identifier: MIT -->
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
|
||||
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
|
||||
<!-- Use configuration provided by KWin Scripting -->
|
||||
<kcfgfile name="kwinrc"/>
|
||||
<!-- Use group name provided by the KWin Scripting -->
|
||||
<group name="Script-bismuth">
|
||||
<!-- This is basically copy-paste from the old configuration file -->
|
||||
<entry name="debug" type="Bool">
|
||||
<label>Enable logging</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
|
||||
<entry name="enableTileLayout" type="Bool">
|
||||
<label>Enable/disable Tile layout</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
|
||||
<entry name="enableMonocleLayout" type="Bool">
|
||||
<label>Enable/disable Monocle layout</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
|
||||
<entry name="enableThreeColumnLayout" type="Bool">
|
||||
<label>Enable/disable Three Column layout</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
|
||||
<entry name="enableSpiralLayout" type="Bool">
|
||||
<label>Enable/disable Spiral layout</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
|
||||
<entry name="enableSpreadLayout" type="Bool">
|
||||
<label>Enable/disable Spread layout</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
|
||||
<entry name="enableStairLayout" type="Bool">
|
||||
<label>Enable/disable Stair layout</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
|
||||
<entry name="enableQuarterLayout" type="Bool">
|
||||
<label>Enable/disable Quarter layout</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
|
||||
<entry name="enableFloatingLayout" type="Bool">
|
||||
<label>Enable/disable Floating layout</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
|
||||
<entry name="ignoreActivity" type="String">
|
||||
<label>Do not apply tiling on some activities(comma-separated list of activity names)</label>
|
||||
<default></default>
|
||||
</entry>
|
||||
|
||||
<entry name="ignoreClass" type="String">
|
||||
<label>Ignore windows with certain classes(comma-separated list)</label>
|
||||
<default>yakuake,spectacle,Conky</default>
|
||||
</entry>
|
||||
|
||||
<entry name="ignoreRole" type="String">
|
||||
<label>Ignore windows with specific role(comma-separated list)</label>
|
||||
<default>quake</default>
|
||||
</entry>
|
||||
|
||||
<entry name="ignoreScreen" type="String">
|
||||
<label>Do not apply tiling on some screens(comma-separated list of screen number)</label>
|
||||
<default></default>
|
||||
</entry>
|
||||
|
||||
<entry name="ignoreTitle" type="String">
|
||||
<label>Ignore windows with certain string in title(comma-separated list)</label>
|
||||
<default></default>
|
||||
</entry>
|
||||
|
||||
<entry name="floatingClass" type="String">
|
||||
<label>Float windows with certain classes(comma-separated list)</label>
|
||||
<default></default>
|
||||
</entry>
|
||||
|
||||
<entry name="floatingTitle" type="String">
|
||||
<label>Float windows with certain string in title(comma-separated list)</label>
|
||||
<default></default>
|
||||
</entry>
|
||||
|
||||
<entry name="floatUtility" type="Bool">
|
||||
<label>Automatically float utility windows (Dialog, Splash, Utility)</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
|
||||
<entry name="layoutPerActivity" type="Bool">
|
||||
<label>Use separate layouts per activity.</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
|
||||
<entry name="layoutPerDesktop" type="Bool">
|
||||
<label>Use separate layouts per desktop.</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
|
||||
<entry name="maximizeSoleTile" type="Bool">
|
||||
<label>If there is only one tile on the screen, remove screen gap and its borde, making it appear almost fullscreen.</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
|
||||
<entry name="monocleMaximize" type="Bool">
|
||||
<label>Always maximize windows in Monocle layout</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
|
||||
<entry name="monocleMinimizeRest" type="Bool">
|
||||
<label>Minimize other tiles than the current one in Monocle layout</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
|
||||
<entry name="keepFloatAbove" type="Bool">
|
||||
<label>Keep tiled windows below floating windows</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
|
||||
<entry name="noTileBorder" type="Bool">
|
||||
<label>Remove borders of tiled windows</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
|
||||
<entry name="preventMinimize" type="Bool">
|
||||
<label>Prevent windows from minimizing</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
|
||||
<entry name="preventProtrusion" type="Bool">
|
||||
<label>Prevent windows from protruding out of screen</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
|
||||
<entry name="screenGapLeft" type="Int">
|
||||
<label>Gap between tiles and screen borders (Left)</label>
|
||||
<default>0</default>
|
||||
</entry>
|
||||
|
||||
<entry name="screenGapRight" type="Int">
|
||||
<label>Gap between tiles and screen borders (Right)</label>
|
||||
<default>0</default>
|
||||
</entry>
|
||||
|
||||
<entry name="screenGapTop" type="Int">
|
||||
<label>Gap between tiles and screen borders (Top)</label>
|
||||
<default>0</default>
|
||||
</entry>
|
||||
|
||||
<entry name="screenGapBottom" type="Int">
|
||||
<label>Gap between tiles and screen borders (Bottom)</label>
|
||||
<default>0</default>
|
||||
</entry>
|
||||
|
||||
<entry name="tileLayoutGap" type="Int">
|
||||
<label>Gap between tiles in Tile layout</label>
|
||||
<default>0</default>
|
||||
</entry>
|
||||
|
||||
<entry name="limitTileWidth" type="Bool">
|
||||
<label>Limit the width of tiles</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
|
||||
<entry name="limitTileWidthRatio" type="Double">
|
||||
<label>Ratio of maximum tile width to the height of screen</label>
|
||||
<default>1.6</default>
|
||||
</entry>
|
||||
|
||||
<entry name="newWindowAsMaster" type="Bool">
|
||||
<label>Put new window as master</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
|
11
src/kcm/bismuth_config.kcfgc
Normal file
11
src/kcm/bismuth_config.kcfgc
Normal file
@ -0,0 +1,11 @@
|
||||
# SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
# See: https://api.kde.org/frameworks/kconfig/html/kconfig_compiler.html
|
||||
File=bismuth_config.kcfg
|
||||
NameSpace=Bismuth
|
||||
ClassName=Config
|
||||
Mutators=true
|
||||
ParentInConstructor=true
|
||||
GenerateProperties=true
|
||||
UseEnumTypes=true
|
62
src/kcm/package/contents/ui/Appearance.qml
Normal file
62
src/kcm/package/contents/ui/Appearance.qml
Normal file
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kcm 1.5 as KCM
|
||||
import org.kde.kirigami 2.7 as Kirigami
|
||||
|
||||
import "./components" as BIC
|
||||
|
||||
Kirigami.FormLayout {
|
||||
id: appearanceTab
|
||||
|
||||
Item {
|
||||
Kirigami.FormData.isSection: true
|
||||
Kirigami.FormData.label: i18n("Outer Gaps")
|
||||
}
|
||||
|
||||
BIC.PixelsConfigSpinBox {
|
||||
Kirigami.FormData.label: i18n("Left:")
|
||||
settingName: "screenGapLeft"
|
||||
}
|
||||
|
||||
BIC.PixelsConfigSpinBox {
|
||||
Kirigami.FormData.label: i18n("Top:")
|
||||
settingName: "screenGapTop"
|
||||
}
|
||||
|
||||
BIC.PixelsConfigSpinBox {
|
||||
Kirigami.FormData.label: i18n("Right:")
|
||||
settingName: "screenGapRight"
|
||||
}
|
||||
|
||||
BIC.PixelsConfigSpinBox {
|
||||
Kirigami.FormData.label: i18n("Bottom:")
|
||||
settingName: "screenGapBottom"
|
||||
}
|
||||
|
||||
Item {
|
||||
Kirigami.FormData.isSection: true
|
||||
Kirigami.FormData.label: "Inner Gaps"
|
||||
}
|
||||
|
||||
BIC.PixelsConfigSpinBox {
|
||||
Kirigami.FormData.label: i18n("All:")
|
||||
settingName: "tileLayoutGap"
|
||||
}
|
||||
|
||||
Kirigami.Separator {
|
||||
Kirigami.FormData.isSection: true
|
||||
}
|
||||
|
||||
BIC.ConfigCheckBox {
|
||||
text: i18n("No borders around tiled windows")
|
||||
settingName: "noTileBorder"
|
||||
}
|
||||
}
|
||||
|
137
src/kcm/package/contents/ui/Behaviour.qml
Normal file
137
src/kcm/package/contents/ui/Behaviour.qml
Normal file
@ -0,0 +1,137 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kcm 1.5 as KCM
|
||||
import org.kde.kirigami 2.7 as Kirigami
|
||||
|
||||
import "./components" as BIC
|
||||
import "./views" as BIView
|
||||
|
||||
Kirigami.FormLayout {
|
||||
id: behaviorTab
|
||||
|
||||
Item {
|
||||
Kirigami.FormData.isSection: true
|
||||
Kirigami.FormData.label: i18n("Layouts")
|
||||
}
|
||||
|
||||
BIC.ConfigCheckBox {
|
||||
Kirigami.FormData.label: i18n("Separate layouts for each:")
|
||||
text: i18n("Activity")
|
||||
settingName: "layoutPerActivity"
|
||||
}
|
||||
|
||||
BIC.ConfigCheckBox {
|
||||
text: i18n("Virtual Desktop")
|
||||
settingName: "layoutPerDesktop"
|
||||
}
|
||||
|
||||
QQC2.Button {
|
||||
id: configureLayoutsButton
|
||||
icon.name: "document-edit"
|
||||
text: i18n("Customize Layouts...")
|
||||
onClicked: () => kcm.push("./views/Layouts.qml")
|
||||
}
|
||||
|
||||
Item {
|
||||
Kirigami.FormData.isSection: true
|
||||
Kirigami.FormData.label: i18n("Windows")
|
||||
}
|
||||
|
||||
BIC.ConfigCheckBox {
|
||||
text: i18n("Maximize sole window")
|
||||
settingName: "maximizeSoleTile"
|
||||
}
|
||||
|
||||
BIC.ConfigCheckBox {
|
||||
text: i18n("Floating windows always on top")
|
||||
settingName: "keepFloatAbove"
|
||||
}
|
||||
|
||||
QQC2.ButtonGroup {
|
||||
id: windowSpawnPositionGroup
|
||||
}
|
||||
|
||||
QQC2.RadioButton {
|
||||
Kirigami.FormData.label: i18n("Spawn windows at:")
|
||||
text: i18n("Master area")
|
||||
QQC2.ButtonGroup.group: windowSpawnPositionGroup
|
||||
|
||||
checked: kcm.config.newWindowAsMaster
|
||||
onClicked: kcm.config.newWindowAsMaster = checked
|
||||
|
||||
KCM.SettingStateBinding {
|
||||
configObject: kcm.config
|
||||
settingName: "newWindowAsMaster"
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.RadioButton {
|
||||
text: i18n("The layout's end")
|
||||
QQC2.ButtonGroup.group: windowSpawnPositionGroup
|
||||
|
||||
checked: !kcm.config.newWindowAsMaster
|
||||
onClicked: kcm.config.newWindowAsMaster = !checked
|
||||
|
||||
KCM.SettingStateBinding {
|
||||
configObject: kcm.config
|
||||
settingName: "newWindowAsMaster"
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.Button {
|
||||
id: windowRules
|
||||
icon.name: "document-edit"
|
||||
text: i18n("Window Rules...")
|
||||
onClicked: () => kcm.push("./views/WindowRules.qml")
|
||||
}
|
||||
|
||||
Item {
|
||||
Kirigami.FormData.isSection: true
|
||||
Kirigami.FormData.label: i18n("Restrictions")
|
||||
}
|
||||
|
||||
BIC.ConfigCheckBox {
|
||||
id: restrictWidth
|
||||
text: i18n("Restrict window width")
|
||||
settingName: "limitTileWidth"
|
||||
}
|
||||
|
||||
BIC.RatioConfigSpinBox {
|
||||
Kirigami.FormData.label: i18n("Window Width/Screen Height ratio:")
|
||||
settingName: "limitTileWidthRatio"
|
||||
|
||||
// For some reason we cannot pass a custom property to
|
||||
// extraEnabledConditions, so we have to define it here.
|
||||
// It is also a reason why RatioConfigSpinBox uses
|
||||
// QQC2.SpinBox instead of ConfigSPinBox component
|
||||
KCM.SettingStateBinding {
|
||||
configObject: kcm.config
|
||||
settingName: "limitTileWidthRatio"
|
||||
extraEnabledConditions: restrictWidth.checked
|
||||
}
|
||||
}
|
||||
|
||||
BIC.ConfigCheckBox {
|
||||
text: i18n("Prevent window minimization")
|
||||
settingName: "preventMinimize"
|
||||
}
|
||||
|
||||
BIC.ConfigCheckBox {
|
||||
text: i18n("Prevent window from protruding from its screen")
|
||||
settingName: "preventProtrusion"
|
||||
}
|
||||
|
||||
QQC2.Button {
|
||||
id: workspaceRules
|
||||
icon.name: "document-edit"
|
||||
text: i18n("Workspace Rules...")
|
||||
onClicked: () => kcm.push("./views/WorkspaceRules.qml")
|
||||
}
|
||||
}
|
25
src/kcm/package/contents/ui/components/ConfigCheckBox.qml
Normal file
25
src/kcm/package/contents/ui/components/ConfigCheckBox.qml
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12 as QQC2
|
||||
|
||||
import org.kde.kcm 1.5 as KCM
|
||||
|
||||
QQC2.CheckBox {
|
||||
id: root
|
||||
/**
|
||||
* Name for the config option to represent
|
||||
*/
|
||||
property string settingName
|
||||
|
||||
checked: kcm.config[settingName]
|
||||
onClicked: kcm.config[settingName] = checked
|
||||
|
||||
KCM.SettingStateBinding {
|
||||
configObject: kcm.config
|
||||
settingName: root.settingName
|
||||
}
|
||||
}
|
31
src/kcm/package/contents/ui/components/ConfigSpinBox.qml
Normal file
31
src/kcm/package/contents/ui/components/ConfigSpinBox.qml
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12 as QQC2
|
||||
|
||||
import org.kde.kcm 1.5 as KCM
|
||||
import org.kde.kirigami 2.7 as Kirigami
|
||||
|
||||
QQC2.SpinBox {
|
||||
id: root
|
||||
|
||||
/**
|
||||
* Name for the config option to represent
|
||||
*/
|
||||
property string settingName: ""
|
||||
|
||||
// Implicit dimensions are set to break binding loop
|
||||
implicitWidth: Kirigami.Units.gridUnit * 5
|
||||
implicitHeight: Kirigami.Units.gridUnit * 1.75
|
||||
|
||||
value: kcm.config[settingName]
|
||||
onValueModified: kcm.config[settingName] = value
|
||||
|
||||
KCM.SettingStateBinding {
|
||||
configObject: kcm.config
|
||||
settingName: root.settingName
|
||||
}
|
||||
}
|
25
src/kcm/package/contents/ui/components/ConfigTextField.qml
Normal file
25
src/kcm/package/contents/ui/components/ConfigTextField.qml
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12 as QQC2
|
||||
|
||||
import org.kde.kcm 1.5 as KCM
|
||||
|
||||
QQC2.TextField {
|
||||
id: root
|
||||
/**
|
||||
* Name for the config option to represent
|
||||
*/
|
||||
property string settingName
|
||||
|
||||
text: kcm.config[settingName]
|
||||
onEditingFinished: kcm.config[settingName] = text
|
||||
|
||||
KCM.SettingStateBinding {
|
||||
configObject: kcm.config
|
||||
settingName: root.settingName
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.7 as Kirigami
|
||||
|
||||
ConfigSpinBox {
|
||||
textFromValue: (value, _locale) => `${Number(value).toLocaleString(locale, 'f', 0)} px`
|
||||
valueFromText: (text, locale) => Number.fromLocaleString(locale, text.replace(" px", ""))
|
||||
// Pixels are always positive
|
||||
from: 0
|
||||
to: 512
|
||||
editable: true
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12 as QQC2
|
||||
|
||||
import org.kde.kirigami 2.7 as Kirigami
|
||||
import org.kde.kcm 1.5 as KCM
|
||||
|
||||
QQC2.SpinBox {
|
||||
id: root
|
||||
|
||||
/**
|
||||
* Name for the config option to represent
|
||||
*/
|
||||
property string settingName: ""
|
||||
property int decimals: 2
|
||||
property real realValue: value / 100
|
||||
|
||||
// Implicit dimensions are set to break binding loop
|
||||
implicitWidth: Kirigami.Units.gridUnit * 5
|
||||
implicitHeight: Kirigami.Units.gridUnit * 1.75
|
||||
|
||||
from: 5
|
||||
to: 300
|
||||
stepSize: 5
|
||||
editable: true
|
||||
|
||||
validator: DoubleValidator {
|
||||
bottom: Math.min(root.from, root.to)
|
||||
top: Math.max(root.from, root.to)
|
||||
}
|
||||
|
||||
// IDK why, but this is needed to make the SpinBox work
|
||||
Component.onCompleted: () => {
|
||||
root.value = kcm.config[settingName] * 100
|
||||
}
|
||||
|
||||
value: kcm.config[settingName] * 100
|
||||
onValueModified: kcm.config[settingName] = realValue
|
||||
|
||||
textFromValue: (value, locale) => Number(value / 100).toLocaleString(locale, 'f', root.decimals)
|
||||
valueFromText: (text, locale) => Number.fromLocaleString(locale, text) * 100
|
||||
}
|
||||
|
63
src/kcm/package/contents/ui/main.qml
Normal file
63
src/kcm/package/contents/ui/main.qml
Normal file
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.7 as Kirigami
|
||||
import org.kde.kcm 1.5 as KCM
|
||||
|
||||
KCM.SimpleKCM {
|
||||
id: root
|
||||
KCM.ConfigModule.quickHelp: i18n("This module lets you manage various window tiling options.")
|
||||
|
||||
implicitWidth: Kirigami.Units.gridUnit * 38
|
||||
implicitHeight: Kirigami.Units.gridUnit * 35
|
||||
|
||||
// TODO: replace this TabBar-plus-Frame-in-a-ColumnLayout with whatever shakes
|
||||
// out of https://bugs.kde.org/show_bug.cgi?id=394296
|
||||
ColumnLayout {
|
||||
id: tabLayout
|
||||
spacing: 0
|
||||
|
||||
QQC2.TabBar {
|
||||
id: tabBar
|
||||
// Tab styles generally assume that they're touching the inner layout,
|
||||
// not the frame, so we need to move the tab bar down a pixel and make
|
||||
// sure it's drawn on top of the frame
|
||||
z: 1
|
||||
Layout.bottomMargin: -1
|
||||
|
||||
QQC2.TabButton {
|
||||
text: i18n("Appearance")
|
||||
}
|
||||
|
||||
QQC2.TabButton {
|
||||
text: i18n("Behavior")
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.Frame {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
StackLayout {
|
||||
currentIndex: tabBar.currentIndex
|
||||
anchors.fill: parent
|
||||
// This breaks anything inside, that is not FormLayout
|
||||
// but necessary for adequate padding
|
||||
anchors.topMargin: Kirigami.Units.gridUnit * -0.5
|
||||
|
||||
Appearance {}
|
||||
|
||||
// For some reason QML is very British and
|
||||
// refuses to load the Behavior.qml (without "u")
|
||||
Behaviour {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
96
src/kcm/package/contents/ui/views/Layouts.qml
Normal file
96
src/kcm/package/contents/ui/views/Layouts.qml
Normal file
@ -0,0 +1,96 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kcm 1.5 as KCM
|
||||
import org.kde.kirigami 2.7 as Kirigami
|
||||
|
||||
import "../components" as BIC
|
||||
|
||||
Kirigami.Page {
|
||||
id: root
|
||||
title: "Window Layouts"
|
||||
|
||||
ListModel {
|
||||
id: layoutsModel
|
||||
ListElement {
|
||||
name: "Tile"
|
||||
settingName: "enableTileLayout"
|
||||
}
|
||||
ListElement {
|
||||
name: "Monocle"
|
||||
settingName: "enableMonocleLayout"
|
||||
editable: true
|
||||
}
|
||||
ListElement {
|
||||
name: "Three Column"
|
||||
settingName: "enableThreeColumnLayout"
|
||||
}
|
||||
ListElement {
|
||||
name: "Spiral"
|
||||
settingName: "enableSpiralLayout"
|
||||
}
|
||||
ListElement {
|
||||
name: "Spread"
|
||||
settingName: "enableSpreadLayout"
|
||||
}
|
||||
ListElement {
|
||||
name: "Stair"
|
||||
settingName: "enableStairLayout"
|
||||
}
|
||||
ListElement {
|
||||
name: "Quarter"
|
||||
settingName: "enableQuarterLayout"
|
||||
}
|
||||
ListElement {
|
||||
name: "Floating"
|
||||
settingName: "enableFloatingLayout"
|
||||
}
|
||||
}
|
||||
|
||||
KCM.ScrollView {
|
||||
anchors.fill: parent
|
||||
|
||||
view: ListView {
|
||||
model: layoutsModel
|
||||
|
||||
delegate: Kirigami.SwipeListItem {
|
||||
contentItem: RowLayout {
|
||||
RowLayout {
|
||||
BIC.ConfigCheckBox {
|
||||
id: layoutCheckBox
|
||||
settingName: model.settingName
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
text: `${model.name} Layout`
|
||||
}
|
||||
}
|
||||
}
|
||||
actions: [
|
||||
Kirigami.Action {
|
||||
id: editLayout
|
||||
enabled: model.editable && layoutCheckBox.checked
|
||||
visible: model.editable
|
||||
iconName: "edit-rename"
|
||||
tooltip: i18nc("@info:tooltip", "Edit Layout")
|
||||
onTriggered: () => {
|
||||
monocleSheet.open()
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MonocleOverlay {
|
||||
id: monocleSheet
|
||||
parent: root // Without this, overlay does not work
|
||||
}
|
||||
}
|
34
src/kcm/package/contents/ui/views/MonocleOverlay.qml
Normal file
34
src/kcm/package/contents/ui/views/MonocleOverlay.qml
Normal file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kcm 1.5 as KCM
|
||||
import org.kde.kirigami 2.7 as Kirigami
|
||||
|
||||
import "../components" as BIC
|
||||
|
||||
Kirigami.OverlaySheet {
|
||||
id: monocleOverlay
|
||||
|
||||
header: Kirigami.Heading {
|
||||
text: i18nc("@title:window", "Monocle Layout Settings")
|
||||
}
|
||||
|
||||
Kirigami.FormLayout {
|
||||
BIC.ConfigCheckBox {
|
||||
text: i18n("Fully maximize windows (no borders, no gaps)")
|
||||
settingName: "monocleMaximize"
|
||||
}
|
||||
|
||||
BIC.ConfigCheckBox {
|
||||
text: i18n("Minimize unfocused windows")
|
||||
settingName: "monocleMinimizeRest"
|
||||
}
|
||||
}
|
||||
}
|
69
src/kcm/package/contents/ui/views/WindowRules.qml
Normal file
69
src/kcm/package/contents/ui/views/WindowRules.qml
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kcm 1.5 as KCM
|
||||
import org.kde.kirigami 2.7 as Kirigami
|
||||
|
||||
import "../components" as BIC
|
||||
|
||||
Kirigami.Page {
|
||||
id: root
|
||||
title: "Window Rules"
|
||||
|
||||
Kirigami.FormLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
Item {
|
||||
Kirigami.FormData.isSection: true
|
||||
Kirigami.FormData.label: i18n("Ignore Windows")
|
||||
}
|
||||
|
||||
BIC.ConfigTextField {
|
||||
Kirigami.FormData.label: "With classes:"
|
||||
placeholderText: "Classes (comma separated)"
|
||||
settingName: "ignoreClass"
|
||||
implicitWidth: Kirigami.Units.gridUnit * 20
|
||||
}
|
||||
|
||||
BIC.ConfigTextField {
|
||||
Kirigami.FormData.label: "With titles:"
|
||||
placeholderText: "Titles (comma separated)"
|
||||
settingName: "ignoreTitle"
|
||||
}
|
||||
|
||||
BIC.ConfigTextField {
|
||||
Kirigami.FormData.label: "With roles:"
|
||||
placeholderText: "Roles (comma separated)"
|
||||
settingName: "ignoreRole"
|
||||
}
|
||||
|
||||
Item {
|
||||
Kirigami.FormData.isSection: true
|
||||
Kirigami.FormData.label: i18n("Float Windows")
|
||||
}
|
||||
|
||||
BIC.ConfigTextField {
|
||||
Kirigami.FormData.label: "With classes:"
|
||||
placeholderText: "Classes (comma separated)"
|
||||
settingName: "floatingClass"
|
||||
}
|
||||
|
||||
BIC.ConfigTextField {
|
||||
Kirigami.FormData.label: "With titles:"
|
||||
placeholderText: "Titles (comma separated)"
|
||||
settingName: "floatingTitle"
|
||||
}
|
||||
|
||||
BIC.ConfigCheckBox {
|
||||
text: "With utility roles"
|
||||
settingName: "floatUtility"
|
||||
}
|
||||
}
|
||||
}
|
42
src/kcm/package/contents/ui/views/WorkspaceRules.qml
Normal file
42
src/kcm/package/contents/ui/views/WorkspaceRules.qml
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Mikhail Zolotukhin <mail@genda.life>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kcm 1.5 as KCM
|
||||
import org.kde.kirigami 2.7 as Kirigami
|
||||
|
||||
import "../components" as BIC
|
||||
|
||||
Kirigami.Page {
|
||||
id: root
|
||||
title: "Workspace Rules"
|
||||
|
||||
Kirigami.FormLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
Item {
|
||||
Kirigami.FormData.isSection: true
|
||||
Kirigami.FormData.label: i18n("Disable Tiling")
|
||||
}
|
||||
|
||||
BIC.ConfigTextField {
|
||||
Kirigami.FormData.label: "On Activities:"
|
||||
placeholderText: "Activities names (comma separated)"
|
||||
settingName: "ignoreActivity"
|
||||
implicitWidth: Kirigami.Units.gridUnit * 20
|
||||
}
|
||||
|
||||
BIC.ConfigTextField {
|
||||
Kirigami.FormData.label: "On Screens:"
|
||||
placeholderText: "Screen numbers (comma separated)"
|
||||
settingName: "ignoreScreen"
|
||||
// implicitWidth: Kirigami.Units.gridUnit * 20
|
||||
}
|
||||
}
|
||||
}
|
18
src/kcm/package/metadata.desktop
Normal file
18
src/kcm/package/metadata.desktop
Normal file
@ -0,0 +1,18 @@
|
||||
# SPDX-FileCopyrightText: none
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
[Desktop Entry]
|
||||
Name=Window Tiling
|
||||
Comment=Configure Window Tiling specific options
|
||||
Encoding=UTF-8
|
||||
Type=Service
|
||||
Icon=bismuth
|
||||
X-KDE-Library=kcm_bismuth
|
||||
X-KDE-ServiceTypes=KCModule
|
||||
X-KDE-FormFactors=desktop,handset,tablet,mediacenter
|
||||
X-Plasma-MainScript=ui/main.qml
|
||||
X-KDE-System-Settings-Parent-Category=windowmanagement
|
||||
X-KDE-Keywords=KWin,Script,Tiling,Bismuth,Window,WM,Layout,Gaps,Borders,Rules,Minimization,Float
|
||||
X-KDE-ParentApp=kcontrol
|
||||
X-KDE-PluginInfo-Name=kcm_bismuth
|
Loading…
Reference in New Issue
Block a user