Releases: linkfrg/ignis
v0.5
It took 3 months to prepare this release and here we go!
This update mainly focuses on rethinking and refactoring some parts of Ignis, but it include many new features & fixes too!
Breaking Changes
Options
Options Service is removed, introducing the new OptionManager
& Options
API instead!
Now all options for all services of Ignis will be in one place, and one class to manage them all.
Migration guide:
- Notification Service:
dnd
,popup_timeout
,max_popups_count
are removed, use corresponding options inignis.options.Options
. E.g., replacenotifications.dnd
withoptions.notifications.dnd
- Recorder Service:
bitrate
,default_file_location
,default_filename
properties are removed. All the same like with Notification Service. - Applications Service: public API hasn't changed
- Wallpaper Service:
wallpaper
property is removed. Useoptions.wallpaper.wallpaper_path
.
If you use Options Service to define your custom options, move to the new OptionsManager
API.
More info is available in the documentation.
Asyncio
asyncio
integration! Some functions are asynchronous now. Use await
or asyncio.create_task()
to call them.
DBusProxy
new_async()
get_dbus_property_async()
set_dbus_property_async()
BluetoothDevice
connect_to()
disconnect_from()
WifiAccessPoint
commit_changes_async()
connect_to()
connect_to_graphical()
disconnect_from()
forget()
EthernetDevice
connect_to()
disconnect_from()
VpnConnection
connect_to()
disconnect_from()
WifiDevice
scan()
Utils.exec_sh_async()
Utils.read_file_async()
Utils.write_file_async()
Widget.FileDialog.open_dialog()
Plus, methods of some services are synchronous and have their explicit async versions now.
Affected methods:
-
MprisPlayer
next()
previous()
pause()
play()
play_pause()
stop()
seek()
-
SystemTrayItem
activate()
secondary_activate()
context_menu()
scroll()
-
SystemdUnit
start()
stop()
restart()
This also affects some property setters:
BacklightDevice.brightness
setter is now synchronous, you can use its asynchronous version which is available as usual method: set_brightness_async()
.
Same for BacklightService.brightness
and MprisPlayer.position
.
Explicit GObject Property type
#157 replaces GObject.Property
with the new IgnisProperty
class.
The main difference with IgnisProperty
is that it can determine the property type automatically based on the return type of the getter
.
This greatly reduces code repetition, as it is sufficient to specify only the return type for the getter function.
Since properties have explicit types, their value can only be of the that defined type because it is now controlled on the GObject/C side, which doesn't support dynamic types.
It means you can't set None
as a value for a property which type is bool/int/str/float
or GObject/GType.
If you use .bind()
, you have to add an additional check if the new value is None
.
Otherwise, an exception like this will be raised:
TypeError: could not convert None to type 'gdouble' when setting property 'IgnisScale.value'
Hyprland Service moved to GObject-based objects
#171 brings objects inherited from IgnisGObject
for Hyprland Service, replacing usual python dictionaries.
This approach allows to bind properties and other GObject features.
New classes:
HyprlandWorkspace
HyprlandWindow
HyprlandKeyboard
Migration Guide:
- Since these objects are not dictionaries anymore, you have to get properties like usual class attributes:
# Old
hyprland.active_workspace["id"]
# New
hyprland.active_workspace.id
HyprlandService.kb_layout
is removed, useHyprlandService.main_keyboard.active_keymap
instead.HyprlandService.switch_kb_layout()
is removed, useHyprlandService.main_keyboard.switch_layout()
instead (to restore the old functionality pass"next"
as an argument to it).HyprlandService.workspaces
will not be notified on the active workspace change anymore.
If you want to restore the old functionality, usebind_many()
:
# Old
hyprland.bind(
"workspaces",
transform=lambda value: [WorkspaceButton(i) for i in value],
)
# New
hyprland.bind_many(
["workspaces", "active_workspace"],
transform=lambda workspaces, *_: [
WorkspaceButton(i) for i in workspaces
],
)
Niri Service moved to GObject-based objects
#181 introduces GObject-based objects for Niri Service.
A few notes:
- Since these objects are not dictionaries anymore, you have to get properties like usual class attributes
NiriService.kb_layout
is removed, useNiriService.keyboard_layouts.current_name
instead.NiriService.active_workspaces
has been dropped, to avoid introducing a separate data structure (list) that needs to be kept up to date. Active workspaces can still be extracted fromNiriService.workspaces
(eachNiriWorkspace
object exposes theis_active
property).NiriService.send_command
now performs json serialization of thecmd
argument and adds a trailing newline ("\n") to the resulting string, thus eliminating the need to pre-process any argument passed to this method.
See updated docs for more info.
Other Breaking Changes
- #103:
Binding.target_property
removed, useBinding.target_properties
(list) instead - #146: logs are stored at
$XDG_STATE_HOME/ignis/ignis.log
(~/.local/state/ignis/ignis.log
) instead of~/.ignis/ignis.log
- The minimal required version of PyGObject is now 3.50.0
- Now
Utils.FileMonitor.flags
usesGio.FileMonitorFlags
, notstr
- chore!: rename
DBusProxy.proxy
->gproxy
for clarity - refactor!: overhaul
DBusProxy
initialization & add support for async initialization (#142) - chore!: remove
Utils.download_image()
as unnecessary - feat!: wrap gvc instead of using git submodule (#109)
New Features
- feat!: allow binding multiple properties (IgnisGObject.bind_many()) (#103)
- feat: add Widget.Stack (Widget.StackPage, Widget.StackSwitcher) (#107)
- feat: Support installation using pip (#92)
- feat: allow skipping gvc build using meson options
- feat: allow skipping dependency check using meson options
- feat(
Widget.Window
): adddynamic_input_region
property - feat: add
Utils.get_monitors()
- feat(
IgnisApp
): addreload_on_monitors_change
property (closes #87) - feat: allow gtk css priority to be overridden (#116)
- feat: support Grass Sass compiler as a fallback (#123)
- feat(
Widget.EventBox
): allow custom scroll flags (#129) - feat: allow custom command format for
Application.launch()
- feat: add
Application.launch_uwsm()
(#134) - feat(
Application
): addis_terminal
property - feat(
Application
): allow running terminal applications using a separate format (closes #141) - feat(
DBusProxy
): make__get_dbus_property
and__set_dbus_property
public - feat(
DBusProxy
): addget_dbus_property_async()
&set_dbus_property_async()
- feat!: follow XDG base directories (#144)
- feat: add
Utils.snake_to_pascal()
&Utils.pascal_to_snake()
Wifi
: Allow get and change PSK (#131)- feat: log python warnings
- feat!: asyncio integration (#152)
- feat: log exceptions from asynchronous functions
- feat: add
ConnectionManager
&DBusConnectionManager
(#159) - feat(
Utils
): add functions for file operations (#149) - feat(
NiriService
): addwindows
property (#164) - feat: add
Utils.get_app_icon_name()
(#167) - feat(
HyprlandService
): addget_workspace_by_id()
method - feat: add
DataGObject
- feat(
DBusProxy
): addcall()
&call_async()
methods - feat(
DBusProxy
): support calling D-Bus methods asynchronously using pythonic way - feat!(
DBusMenu
): move to async - feat(
HyprlandService
): sync workspace on "renameworkspace" event (#172) - feat(
FetchService
): add k10temp cpu temperature support (#187) - feat: add
ignis.is_editable_install
variable - feat(
HyprlandService
): addwindows
property (#210) - feat(
HyprlandService
): addget_windows_on_workspace()
method - feat(
OptionsManager
): Add support for hot-reloading when the file is modified externally (#198) - feat: store compiled css file in a random temporary directory (#211)
- feat(
OptionsManager
): implementTrackedList
(#215) - feat: support modifying
options.applications.pinned_apps
(#216) - feat(
HyprlandService
): addmonitors
property (#219)
Fixes
- fix(nix): add
gnome-bluetooth
toGI_TYPELIB_PATH
(#97) - fix(
NetworkService
): exceptKeyError
on.pop()
- fix(
Vpn
): notifyactive-vpn-id
&is-connected
when adding/removing an active connection - fix(
Widget.Box
): notify child onappend()
,remove()
, andprepend()
- fix(
Widget.Window
): change input region after realize if surface is None - fix(
SystemTrayService
): do not add an item if itsbus_name
is already present inself._items
(closes #118) - fix(
SystemTrayService
): add icon theme of item to search path (#120) - fix: use triple double quotes (
"""
) in__commit__.py
- fix: escape commit message for correct string syntax in
__commit__.py
- fix(nix): do not use
substituteInPlace
for/bin/sass
(#130) - fix(
Wifi
): do not add access points with the same bssid - refactor(
Widget.PopoverMenu
): improve menu generation logic (#136) - fix(
SystemTrayService
): initialize item proxy asynchronously (closes #140) - fix: use
GLib.Error
instead ofGLib.GError
- fix(
SystemTrayItem
): move to asynchronous property synchronization (#147) - Wi-Fi AP Connection Fixes (...
v0.4
Happy New Year everyone! Bringing you a new update with many new features and fixes...
Breaking Changes
- HyprlandIPCNotFoundError doesn't raise during Hyprland Service initialization, use the new
HyprlandService.is_available
property instead
New Features
- feat(nix): remove submodules for nix build (#43)
- feat: add HyprlandService.is_available property
- feat: Niri Service (#54)
- feat: Hyprland keyboard layout widget in example bar (also #54)
- feat: allow passing
**kwargs
toUtils.exec_sh()
- feat: IgnisApp.add_icons() (#53)
- feat: Power Menu in example bar (#57)
- feat(network): support wireguard vpn connections (#63)
- feat: Bluetooth Service (#28)
- feat(fetch): add cpu_temp property (#73)
- feat: Systemd Service (#62)
- feat: Utils.DebounceTask & Utils.debounce (#76)
- feat(Widget.EventBox): add support for on scroll [right, left] events (#82)
- feat(network): refactor signal handling (#80)
- feat: Utils.listen_socket() & Utils.send_socket(): add 'errors' argument
- feat(logging): log 'Happy New Year!'
Fixes
- fix(nix): add gstreamer, gst-plugins, pipewire to buildInputs (#44)
- fix: UPower Device State always return false (#59)
- fix: display the latest notification in example bar
- fix: use the icon provided by a Spotify installation when it is unavailable in the icon theme (#67)
- fix(nix): prefix PATH instead of overwriting it (#72)
- fix: Widget.Grid: prevent from calling __apply() two times during init
- fix(nix): use librsvg pixbuf module loader cache to allow loading SVG icons (#78)
- fix(notifications): dismiss the oldest popup in the list (0), not the newest (-1)
- fix(docs): Widget.Window.monitor: move the docstring from the setter to the GObject.Property itself
- fix(network): use rsn_flags & wpa_flags to check the security protocol of an access point (#86)
- fix: remove windows gracefully by overriding destroy() and unreliaze() methods
- fix(network): WifiConnectDialog: use an unique window name based on the bssid (#89)
- fix(hyprland): use 'errors=ignore' when decoding the response from the socket (closes: #91)
- fix(niri): use 'errors=ignore' when decoding the response from the socket
- fix(network): Ethernet: watch for available device connections
- fix: do not remove window on close request when hide_on_close is True
- other minor typing and typos fixes
Misc
- docs: update user/installation.rst
- add ruff to dev.txt
- stubs: remove UPowerGlib.pyi (not required)
- github(workflows): run ruff & mypy on examples
- move ruff config to pyproject.toml
- specify default selection for ruff
- docs: add a note about symbolic icons in IgnisApp.add_icons()
- README.md: add note about #60
- fix(stubs/NM.pyi): typing issue with enum with zero members
PRs
- feat(nix): remove submodules for nix build by @ratson in #43
- fix(nix): add GStreamer & PipeWire to build inputs by @0x006E in #44
- feat: Niri Service by @regenman in #54
- feat: IgnisApp.add_icons() by @linkfrg in #53
- fix: UPower Device State always return false by @newor0599 in #59
- feat: Power Menu in example bar by @regenman in #57
- feat(network): support wireguard vpn connections by @regenman in #63
- fix: use the icon provided by a Spotify installation when it is unavailable in the icon theme by @linkfrg in #67
- feat: Bluetooth Service by @linkfrg in #28
- fix(nix): prefix PATH instead of overwriting it by @campbellcole in #72
- feat: add cpu_temp to fetch service by @trolljoe in #73
- feat: Systemd Service by @regenman in #62
- fix(nix): use librsvg pixbuf module loader cache to allow loading SVG icons by @campbellcole in #78
- feat: Utils.DebounceTask & Utils.debounce by @linkfrg in #76
- Feat(Widget.EventBox): Add support for right & left scroll events by @regenman in #82
- feat(network): refactor signal handling by @linkfrg in #80
- fix(network): use rsn_flags & wpa_flags to check the security protocol of an access point by @linkfrg in #86
- fix(network): WifiConnectDialog: use an unique window name based on the bssid by @linkfrg in #89
New Contributors
- @0x006E made their first contribution in #44
- @regenman made their first contribution in #54
- @newor0599 made their first contribution in #59
- @campbellcole made their first contribution in #72
- @trolljoe made their first contribution in #73
Full Changelog: v0.3...v0.4
v0.3
Breaking Changes
- fix!(gobject): IgnisGObject.set_property: do not return when a value is None
- feat!(Utils.ThreadTask): use explicit run()
- feat!(Utils.FileMonitor): pass
self
as the first argument to a callback - feat!(applications): rename search() -> search_apps(); add support for searching in a custom list of applications (new required argument)
New Features
- feat: add Utils.get_ignis_branch() and Utils.get_ignis_commit_msg()
- feat(cli): print the git branch and the git commit message in --version
- feat(cli): add
systeminfo
subcommand - feat: add support for custom paths and xml in
Utils.load_interface_xml()
- feat: DBusProxy: add support for system bus
- feat: DBusProxy: add support for setting dbus properties
- feat: Backlight Service (#16)
- feat: add UPower Service (#10, #26)
- feat(logging): log GTK errors
- feat: add
Utils.send_socket()
&Utils.listen_socket()
- feat(network): add VPN functionality (#29)
- feat: Widget.Window: add margin properties
- feat(system tray): SystemTrayItem: add activate(), secondary_activate(), context_menu() and scroll() functions (closes #36)
- feat(Utils.FileMonitor): add the prevent_gc property
Fixes
- fix(Widget.Window): wrong type hint for anchor property;
- fix(Widget.Window): unset all anchors if the anchor property is set to None
- fix(hyprland): messages from sockets is limited by the buffer size (1024/4096 bytes)
- fix(app): reload CSS only on the
changes_done_hint
event type (closes #18) - fix(applications): disable python virtual env for subprocess & set cwd to home dir
- fix(cli): set prog_name explicitly
- fix(dbus menu): call AboutToShow on popup (closes #33)
- fix(notifications): popup_timeout setter function is not working (#38)
- fix(Utils.FileMonitor): "changed" signal is called only if a callback is present
- fix: use TypeAlias annotation for classes in Utils
Other
- github: add issue forms
- github(workflows): build documentation on pull requests
- Package for NixOS (and some fixes for it) (#13, #14, #21, #25)
- docs: fix incorrect import of services in examples (closes #20)
- docs: General improvements to the API Reference (#35)
- docs: refactor versioning stuff
New Contributors
- @somokill made their first contribution in #13
- @gauravsatish made their first contribution in #16
- @ratson made their first contribution in #21
- @tyrypyrking made their first contribution in #29
- @imxnasr made their first contribution in #38
Full Changelog: v0.2...v0.3
v0.2
Breaking Changes
- cli: move to
click
instead ofargparse
:- subcommands instead of arguments (e.g.,
quit
instead of--quit
) - to run Ignis, use the
init
subcommand (ignis init
)
- subcommands instead of arguments (e.g.,
Utils.Poll
: passself
as an argument to the callback- Network Service: add support for controlling multiple devices; more functionality for controlling Ethernet
Utils.Poll
: use milliseconds instead of seconds- Use service classes directly:
- remove
ServiceClass
andService
fromignis.services
- add
.get_default()
method to services - add
BaseService
class
- remove
- remove the
app
variable fromignis.app
; use theIgnisApp.get_default()
method instead - feat!(options): add support for option groups
- feat!(options): use the Option class directly
New Features:
- Utils: add
Utils.get_ignis_commit
- switch to using exceptions instead of logging
- App: added
remove_window()
method - CLI: print "No such window" error
- Examples: add examples/bar
- CLI: add support to execute blocks of code
- Recorder: added
pause_recording
and `continue_recording`` methods - Widgets: add
Widget.Arrow
andWidget.ArrowButton
- App: add
is_ready
property - App: add support for multiple style paths (CSS providers)
- Utils: add
Utils.get_current_dir()
- Widgets: add
Widget.RevealerWindow
Fixes:
- App: return value immediately in
__RunPython__
and__RunFile__
- Audio Service: Stream: rounding volume added
- MPRIS Service: fix issue a player sometimes doesn't close
- Widget.FileChooserButton: do not set icon name if the path doesn't exist
- Hyprland Service: except
json.decoder.JSONDecodeError
in__listen_socket()
- Recorder Service: fix memory leak
- Widget.Box: not all children are removed
- Network Service (Wi-Fi): notify
enabled
property; return when unavailable inWifiDevice.scan()
- Network Service: fix some properties not updating or notifying
- Notifications Service: close the old notification when replacing it with a new one
- Notifications Service: do not sort notifications and popups by ID
__init__.py
: removed the extra slash (/) at the end ofCACHE_DIR
- MPRIS Service: notify
art_url
only when necessary - logging: log all unhandled exceptions
- Recorder Service: fix issue where the output file was sometimes corrupted
- mpris: invalid filename when downloading art image from the URL
- add
Variable
class
Other:
- add Ruff and mypy
- remove
post_install.py
- move version from the
VERSION
file to__version__
in__init__.py
- docs: move to pydata Sphinx theme
- move to
loguru
for logging - Recorder Service: move all XDG Desktop Portal stuff to the
SessionManager
class - Widget.Window: raise
ValueError
on invalidinput_width
andinput_height
values - Widget.Window: set default value for
input_width
andinput_height
to 0 - split CLI and
IgnisClient
, move all CLI-related code tocli.py
- docs: simplify the build process
- docs: add checks for Sphinx build; move options creation and
os.makedirs()
to class constructors - docs: add version switcher
- add
py.typed
marker - docs: sort members by source
- Wallpaper Service: use
WallpaperLayerWindow
instead ofWidget.Window
- use pygobject-stubs; add stubs for
Gvc
,NM
,Gtk4LayerShell
- docs: use sphinx_design
- docs: use sphinx_copybutton
- split services into separate directories and files
- dbus: use async calls using `result_handler``
- docs: generate widgets and utils API reference files when building documentation (mock imports)
- docs: improve developer docs
- docs: add module names
New Contributors
Full Changelog: v0.1...v0.2