binary + installer

This commit is contained in:
Zacharias-Brohn
2026-02-18 18:53:11 +01:00
parent 01e94a10ab
commit 457007f74d
21 changed files with 270 additions and 2 deletions
+2 -1
View File
@@ -7,10 +7,11 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(ENABLE_MODULES "plugin" CACHE STRING "Modules to build/install")
set(ENABLE_MODULES "plugin;shell" CACHE STRING "Modules to build/install")
set(INSTALL_LIBDIR "usr/lib/ZShell" CACHE STRING "Library install dir")
set(INSTALL_QMLDIR "usr/lib/qt6/qml" CACHE STRING "QML install dir")
set(INSTALL_QSCONFDIR "etc/xdg/quickshell/zshell" CACHE STRING "Quickshell config install dir")
add_compile_options(
-Wall -Wextra -Wpedantic -Wshadow -Wconversion
+8
View File
@@ -41,6 +41,14 @@ Searcher {
forward: false
})
IpcHandler {
target: "wallpaper"
function set(path: string): void {
root.setWallpaper(path);
}
}
FileSystemModel {
id: wallpapers
+9
View File
@@ -3,6 +3,7 @@ pragma ComponentBehavior: Bound
import Quickshell
import Quickshell.Wayland
import Quickshell.Hyprland
import Quickshell.Io
import QtQuick
import QtQuick.Effects
import qs.Components
@@ -33,6 +34,14 @@ Scope {
lock: lock
}
IpcHandler {
target: "lock"
function lock() {
return lock.locked = true;
}
}
CustomShortcut {
name: "lock"
description: "Lock the current session"
+29
View File
@@ -0,0 +1,29 @@
pkgname='zshell'
pkgver=0.1.0
pkgrel=1
pkgdesc='The cli for zshell'
arch=('any')
url='https://github.com/Zacharias-Brohn/z-bar-qt'
license=('GPL-3.0-only')
depends=('python' 'python-pillow' 'python-materialyoucolor' 'libnotify' 'swappy' 'dart-sass'
'app2unit' 'wl-clipboard' 'dconf' 'cliphist')
makedepends=('python-build' 'python-installer' 'python-hatch' 'python-hatch-vcs')
source=("$pkgname::git+$url.git")
sha256sums=('SKIP')
build() {
cd "${srcdir}/${pkgname}/cli"
python -m build --wheel --no-isolation
cd ..
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/
cmake --build build
}
package() {
cd "${srcdir}/${pkgname}/cli"
python -m installer --destdir="$pkgdir" dist/*.whl
cd ..
DESTDIR="$pkgdir" cmake --install build
}
Executable
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
cd "$(dirname $0)/../src" || exit
python3 -m zshell "$@"
Binary file not shown.
+27
View File
@@ -0,0 +1,27 @@
[build-system]
requires = ["hatchling >= 1.26"]
build-backend = "hatchling.build"
[project]
name = "zshell"
requires-python = ">=3.13"
version = "0.1.0"
dependencies = [
"typer",
"pillow",
"materialyoucolor"
]
[project.scripts]
zshell-cli = "zshell:main"
[tool.hatch.version]
source = "vcs"
[tool.hatch.build.targets.sdist]
only-include = [
"src",
]
[tool.ruff]
line-length = 120
+14
View File
@@ -0,0 +1,14 @@
from __future__ import annotations
import typer
from zshell.subcommands import shell, scheme, screenshot, wallpaper
app = typer.Typer()
app.add_typer(shell.app, name="shell")
app.add_typer(scheme.app, name="scheme")
app.add_typer(screenshot.app, name="screenshot")
app.add_typer(wallpaper.app, name="wallpaper")
def main() -> None:
app()
+4
View File
@@ -0,0 +1,4 @@
from . import main
if __name__ == "__main__":
main()
Binary file not shown.
Binary file not shown.
Binary file not shown.
+113
View File
@@ -0,0 +1,113 @@
from typing import Annotated
import typer
import json
from pathlib import Path
from PIL import Image
from materialyoucolor.quantize import QuantizeCelebi
from materialyoucolor.score.score import Score
from materialyoucolor.dynamiccolor.material_dynamic_colors import MaterialDynamicColors
from materialyoucolor.hct.hct import Hct
app = typer.Typer()
@app.command()
def generate(
path: Annotated[
Path,
typer.Option(),
],
output: Annotated[
Path,
typer.Option(),
],
thumbnail: Annotated[
Path,
typer.Option(),
],
scheme: Annotated[
str,
typer.Option()
]
):
match scheme:
case "fruit-salad":
from materialyoucolor.scheme.scheme_fruit_salad import SchemeFruitSalad as Scheme
case 'expressive':
from materialyoucolor.scheme.scheme_expressive import SchemeExpressive as Scheme
case 'monochrome':
from materialyoucolor.scheme.scheme_monochrome import SchemeMonochrome as Scheme
case 'rainbow':
from materialyoucolor.scheme.scheme_rainbow import SchemeRainbow as Scheme
case 'tonal-spot':
from materialyoucolor.scheme.scheme_tonal_spot import SchemeTonalSpot as Scheme
case 'neutral':
from materialyoucolor.scheme.scheme_neutral import SchemeNeutral as Scheme
case 'fidelity':
from materialyoucolor.scheme.scheme_fidelity import SchemeFidelity as Scheme
case 'content':
from materialyoucolor.scheme.scheme_content import SchemeContent as Scheme
case 'vibrant':
from materialyoucolor.scheme.scheme_vibrant import SchemeVibrant as Scheme
case _:
from materialyoucolor.scheme.scheme_fruit_salad import SchemeFruitSalad as Scheme
def generate_thumbnail(image_path, thumbnail_path, size=(128, 128)):
thumbnail_file = Path(thumbnail_path)
image = Image.open(image_path)
image = image.convert("RGB")
image.thumbnail(size, Image.NEAREST)
thumbnail_file.parent.mkdir(parents=True, exist_ok=True)
image.save(thumbnail_path, "JPEG")
def generate_color_scheme(thumbnail_path, output_path):
image = Image.open(thumbnail_path)
pixel_len = image.width * image.height
image_data = image.getdata()
quality = 1
pixel_array = [image_data[_] for _ in range(0, pixel_len, quality)]
result = QuantizeCelebi(pixel_array, 128)
score = Score.score(result)[0]
scheme = Scheme(
Hct.from_int(score),
True,
0.0
)
color_dict = {}
for color in vars(MaterialDynamicColors).keys():
color_name = getattr(MaterialDynamicColors, color)
if hasattr(color_name, "get_hct"):
color_int = color_name.get_hct(scheme).to_int()
color_dict[color] = int_to_hex(color_int)
output_dict = {
"name": "dynamic",
"flavour": "default",
"mode": "dark",
"variant": "tonalspot",
"colors": color_dict
}
output_file = Path(output_path)
output_file.parent.mkdir(parents=True, exist_ok=True)
with open(output_file, "w") as f:
json.dump(output_dict, f, indent=4)
def int_to_hex(argb_int):
return "#{:06X}".format(argb_int & 0xFFFFFF)
try:
generate_thumbnail(path, str(thumbnail))
generate_color_scheme(str(thumbnail), output)
except Exception as e:
print(f"Error: {e}")
with open(output, "w") as f:
f.write(f"Error: {e}")
+18
View File
@@ -0,0 +1,18 @@
import subprocess
import typer
args = ["qs", "-c", "zshell"]
app = typer.Typer()
@app.command()
def start():
subprocess.run(args + ["ipc"] + ["call"] +
["picker"] + ["open"], check=True)
@app.command()
def start_freeze():
subprocess.run(args + ["ipc"] + ["call"] +
["picker"] + ["openFreeze"], check=True)
+26
View File
@@ -0,0 +1,26 @@
import subprocess
import typer
args = ["qs", "-c", "zshell"]
app = typer.Typer()
@app.command()
def kill():
subprocess.run(args + ["kill"], check=True)
@app.command()
def start(no_daemon: bool = False):
subprocess.run(args + ([] if no_daemon else ["-d"]), check=True)
@app.command()
def show():
subprocess.run(args + ["ipc"] + ["show"], check=True)
@app.command()
def log():
subprocess.run(args + ["log"], check=True)
@app.command()
def lock():
subprocess.run(args + ["ipc"] + ["call"] + ["lock"] + ["lock"], check=True)
+14
View File
@@ -0,0 +1,14 @@
import subprocess
import typer
from pathlib import Path
args = ["qs", "-c", "zshell"]
app = typer.Typer()
@app.command()
def set(wallpaper: Path):
subprocess.run(args + ["ipc"] + ["call"] +
["wallpaper"] + ["set"] + [wallpaper], check=True)
+1 -1
View File
@@ -7,5 +7,5 @@
- [ ] Quick toggle for BT, WiFi (modules in the tray do this too)
- [x] Auto hide unless on mouse hover. Also implement bar changes to mute/volume to show notif or show bar for a couple seconds.
- [x] Maybe already possible; have keybinds to show certain menus. I do not want to touch my mouse to see notifications for example. Not everything in the bar needs this, but some would be good to have.
- [ ] Pressing ESC or some obvious button to close nc.
- [x] Pressing ESC or some obvious button to close nc.
- [x] Another branch for development, hold off big changes so that a working bar or if there are big config changes.