License as MIT, KDE support, nix package and flake

This commit is contained in:
Kat Inskip 2023-11-12 12:56:47 -08:00
parent 3c196d83d0
commit 4a18fa6337
Signed by: kat
GPG key ID: 465E64DECEA8CF0F
19 changed files with 219 additions and 39 deletions

7
LICENSE.txt Normal file
View file

@ -0,0 +1,7 @@
Copyright 2023 kittywitch
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,5 +1,5 @@
seconds = 300
automatic = true
interval = 300
rotate = true
source = "konachan"
tags = [
"rating:s"

61
flake.lock generated Normal file
View file

@ -0,0 +1,61 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1694529238,
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1699099776,
"narHash": "sha256-X09iKJ27mGsGambGfkKzqvw5esP1L/Rf8H3u3fCqIiU=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "85f1ba3e51676fa8cc604a3d863d729026a6b8eb",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

21
flake.nix Normal file
View file

@ -0,0 +1,21 @@
{
description = "konawall-py";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = {
self,
nixpkgs,
flake-utils,
...
} @ inputs:
flake-utils.lib.eachDefaultSystem (system: let
pkgs = nixpkgs.legacyPackages.${system};
in {
packages = rec {
konawall-py = pkgs.python3.pkgs.callPackage ./package.nix {};
default = konawall-py;
};
});
}

View file

@ -1,7 +1,7 @@
import logging
import tempfile
import requests
from custom_print import kv_print
from konawall.custom_print import kv_print
"""
Download files given a list of URLs

View file

@ -1,8 +1,8 @@
import sys
import os
import logging
from custom_errors import UnsupportedPlatform
from module_loader import environment_handlers
from konawall.custom_errors import UnsupportedPlatform
from konawall.module_loader import environment_handlers
"""
This detects the DE/WM from the Linux environment because it's not provided by the platform
@ -21,6 +21,7 @@ def detect_linux_environment():
"kde", # qdbus
]
modified_mapping = {
"plasma": "kde",
"fluxbox": "feh",
"blackbox": "feh",
"openbox": "feh",

View file

@ -1,5 +1,5 @@
import subprocess
from module_loader import add_environment
from konawall.module_loader import add_environment
"""
This sets wallpapers on Darwin.

View file

@ -0,0 +1,16 @@
import subprocess
from konawall.module_loader import add_environment
"""
This sets the wallpaper on KDE.
"""
@add_environment("kde_setter")
def set_wallpapers(files: list, displays: list):
for file in files:
kde_script = f"""
for (const desktop of desktops()) {{
desktop.currentConfigGroup = ["Wallpaper", "org.kde.image", "General"]
desktop.writeConfig("Image", "{file}")
}}
"""
subprocess.run(["qdbus", "org.kde.plasmashell", "/PlasmaShell", "org.kde.PlasmaShell.evaluateScript", kde_script])

View file

@ -1,8 +1,8 @@
import os
import ctypes
import logging
from imager import combine_to_viewport
from module_loader import add_environment
from konawall.imager import combine_to_viewport
from konawall.module_loader import add_environment
"""
Pre-setting on Windows

56
konawall/gui.py Normal file → Executable file
View file

@ -9,15 +9,15 @@ import screeninfo
import tomllib
import subprocess
import importlib.metadata
from environment import set_environment_wallpapers, detect_environment
from module_loader import import_dir, environment_handlers, source_handlers
from custom_print import kv_print
from konawall.environment import set_environment_wallpapers, detect_environment
from konawall.module_loader import import_dir, environment_handlers, source_handlers
from konawall.custom_print import kv_print
from humanfriendly import format_timespan
class Konawall(wx.adv.TaskBarIcon):
def __init__(self, version, file_logger):
# Prevents it from closing before it has done any work on macOS
if wx.Platform == "__WXMAC__":
if wx.Platform == "__WXMAC__" or wx.Platform == "__WXGTK__":
self.hidden_frame = wx.Frame(None)
self.hidden_frame.Hide()
@ -37,6 +37,17 @@ class Konawall(wx.adv.TaskBarIcon):
self.wallpaper_rotation_timer = wx.Timer(self, wx.ID_ANY)
# Reload (actually load) the config and modules.
if wx.Platform == "__WXGTK__":
from xdg_base_dirs import xdg_config_home
self.config_path = os.path.join(xdg_config_home(), "konawall", "config.toml")
if wx.Platform == "__WXMAC__":
config_path_string = "~/Library/Application Support/konawall/config.toml"
self.config_path = os.path.expanduser(config_path_string)
elif wx.Platform == "__WXMSW__":
config_path_string = "%APPDATA%\\konawall\\config.toml"
self.config_path = os.path.expandvars(config_path_string)
else:
self.config_path = os.path.join(os.path.expanduser("~"), ".config", "konawall", "config.toml")
self.reload_config()
self.import_modules()
@ -65,7 +76,7 @@ class Konawall(wx.adv.TaskBarIcon):
if "wxMSW" in wx.PlatformInfo:
image = image.resize((16, 16))
elif "wxGTK" in wx.PlatformInfo:
image = image.rescale((22, 22))
image = image.resize((22, 22))
# Write image to temporary file
temp = tempfile.NamedTemporaryFile(suffix=".png", delete=False)
@ -77,7 +88,7 @@ class Konawall(wx.adv.TaskBarIcon):
return icon
def toggle_timed_wallpaper_rotation_status(self):
return f"{'Dis' if self.rotate_wallpapers else 'En'}able Timer"
return f"{'Dis' if self.rotate else 'En'}able Timer"
# Load in our source and environment handlers
def import_modules(self):
@ -88,9 +99,9 @@ class Konawall(wx.adv.TaskBarIcon):
# Load a TOML file's key-value pairs into our class
def load_config(self):
if os.path.isfile("config.toml"):
if os.path.isfile(self.config_path):
# If the config file exists, load it as a dictionary into the config variable.
with open("config.toml", "rb") as f:
with open(self.config_path, "rb") as f:
config = tomllib.load(f)
# for every key-value pair in the config variable , set the corresponding attribute of our class to it
for k, v in config.items():
@ -100,14 +111,14 @@ class Konawall(wx.adv.TaskBarIcon):
# If there is no config file, get complainy.
dialog = wx.MessageDialog(
None,
"No config file found, using defaults.",
f"No config file found at {self.config_path}, using defaults.",
self.title_string,
wx.OK|wx.ICON_INFORMATION
)
dialog.ShowModal()
dialog.Destroy()
# Set some arbitrary defaults
self.rotate_wallpapers = True
self.rotate = True
self.interval = 10*60
self.tags = ["rating:s"]
self.logging = {}
@ -123,7 +134,10 @@ class Konawall(wx.adv.TaskBarIcon):
return item
def create_info_item(menu, label, help=""):
item = wx.MenuItem(menu, wx.ID_ANY, label)
item.Enable(False)
if wx.Platform == "__WXGTK__":
menu.Bind(wx.EVT_MENU, (lambda x: x), id=item.GetId())
else:
item.Enable(False)
menu.Append(item)
return item
def create_separator(menu):
@ -195,21 +209,21 @@ class Konawall(wx.adv.TaskBarIcon):
# Interactively edit the config file
def edit_config_menu_item(self, event):
kv_print("User is editing", "config.toml")
kv_print("User is editing", self.config_path)
# Check if we're on Windows, if so use Notepad
if sys.platform == "win32":
# I don't even know how to detect the default editor on Windows
subprocess.call("notepad.exe config.toml")
subprocess.call(f"notepad.exe {self.config_path}", shell=True)
else:
# Open config file in default editor
subprocess.call(f"{os.environ['SHELL']} {os.environ['EDITOR']} config.toml")
subprocess.call(f"{os.environ['SHELL']} {os.environ['EDITOR']} {self.config_path}", shell=True)
# When file is done being edited, reload config
kv_print("User has edited", "config.toml")
kv_print("User has edited", self.config_path)
self.reload_config()
# Reload the application
def reload_config(self):
kv_print(f"{'Rel' if self.loaded_before else 'L'}oading config from", "config.toml")
kv_print(f"{'Rel' if self.loaded_before else 'L'}oading config from", self.config_path)
self.load_config()
# Handle finding the log level
@ -250,14 +264,14 @@ class Konawall(wx.adv.TaskBarIcon):
# Set whether to rotate wallpapers automatically or not
def toggle_timed_wallpaper_rotation(self, event):
self.rotate_wallpapers = not self.rotate_wallpapers
self.rotate = not self.rotate
self.respect_timed_wallpaper_rotation_toggle()
# Update the timer and the menu item to reflect our current state
def respect_timed_wallpaper_rotation_toggle(self):
if self.rotate_wallpapers and not self.wallpaper_rotation_timer.IsRunning():
if self.rotate and not self.wallpaper_rotation_timer.IsRunning():
self.wallpaper_rotation_timer.Start(1000)
elif not self.rotate_wallpapers and self.wallpaper_rotation_timer.IsRunning():
elif not self.rotate and self.wallpaper_rotation_timer.IsRunning():
self.wallpaper_rotation_timer.Stop()
# Set the time left counter to show that it is disabled
self.timed_wallpaper_rotation_status_menu_item.SetItemLabel(f"Automatic wallpaper rotation disabled")
@ -316,12 +330,12 @@ def main():
version = "testing version"
file_logger = logging.FileHandler("app.log", mode="a")
#console_logger = logging.StreamHandler()
console_logger = logging.StreamHandler()
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[
#console_logger,
console_logger,
file_logger,
]
)

View file

@ -3,7 +3,7 @@ import os
import re
import inspect
import logging
from custom_print import kv_print
from konawall.custom_print import kv_print
global environment_handlers
global source_handlers

View file

View file

@ -1,9 +1,9 @@
import requests
import logging
from custom_print import kv_print
from custom_errors import RequestFailed
from module_loader import add_source
from downloader import download_files
from konawall.custom_print import kv_print
from konawall.custom_errors import RequestFailed
from konawall.module_loader import add_source
from konawall.downloader import download_files
"""
Turn a list of tags and a count into a list of URLs to download from

32
package.nix Normal file
View file

@ -0,0 +1,32 @@
{
lib,
buildPythonPackage,
python311Packages,
}: let
pyproject = builtins.fromTOML (builtins.readFile ./pyproject.toml);
poetryBlock = pyproject.tool.poetry;
dependencyReplacements = {
wxpython = python311Packages.wxPython_4_2;
};
in
buildPythonPackage rec {
pname = poetryBlock.name;
version = poetryBlock.version;
src = ./.;
doCheck = false;
propagatedBuildInputs = let
dependencyNames = lib.attrNames poetryBlock.dependencies;
dependencies = map (name: python311Packages.${name} or dependencyReplacements.${name}) dependencyNames;
in
dependencies;
meta = with lib; {
description = poetryBlock.description;
homepage = poetryBlock.homepage;
license = licenses.${toLower poetryBlock.license};
maintainers = with lib.maintainers; [kittywitch];
};
}

View file

@ -1,6 +1,7 @@
[tool.poetry]
name = "konawall"
version = "0.1.0"
license = "MIT"
description = "A hopefully cross-platform service for fetching wallpapers and setting them"
authors = [
"Kat Inskip <kat@inskip.me>"
@ -10,6 +11,9 @@ packages = [
{include = "konawall"}
]
[tool.poetry.scripts]
gui = "konawall.script"
[tool.poetry.dependencies]
python = "^3.11"
pillow = "^10.0.1"
@ -18,9 +22,8 @@ requests = "^2.31.0"
termcolor = "^2.3.0"
wxpython = "^4.2.1"
humanfriendly = "^10.0"
xdg-base-dirs = "^6.0.1"
[build-system]
requires = [
"poetry-core"
]
requires = [ "poetry-core" ]
build-backend = "poetry.core.masonry.api"

View file

@ -4,3 +4,4 @@ requests
termcolor
wxpython
humanfriendly
xdg-base-dirs

24
setup.py Normal file
View file

@ -0,0 +1,24 @@
from setuptools import setup
with open("README.MD", "r") as f:
long_description = f.read()
import tomllib
with open("pyproject.toml", "rb") as f:
pyproject = tomllib.load(f)
poetryBlock = pyproject["tool"]["poetry"]
setup(
name = poetryBlock["name"],
version = poetryBlock["version"],
author = poetryBlock["authors"][0].split(" <")[0],
author_email = poetryBlock["authors"][0].split(" <")[1][:-1],
description = poetryBlock["description"],
long_description = long_description,
entry_points = {
"console_scripts": [
"konawall = konawall.gui:main",
],
},
)