Package: blighty
Desktop Widget ManagerThink of Conky, but with Python instead of Lua.Synopsis•Requirements•Installation•UsageSynopsisTheBlightyproject is inspired by Conky. In essence, it is a collection of
objects that allow you to quickly create a transparent window that you can draw
on with cairo. But instead of coding your widgets in Lua, that perhaps end up
calling Python as external tools, you can now code them natively in Python.Performance won't be as great as Conky, with probably more resource being used
for the same end result, but native Python support opens up for a lot more
customisation possibilities in a snap of your fingers.There won't be much you can do with minimal effort out of the box while the
project is in its infancy. If you like the idea, you are more than welcome to
contribute to this project!RequirementsX11Xineramacairopython3python3-gi (only for GTK Windows)gir1.2-gtk-3.0 (only for GTK Windows)gir1.2-glib-2.0 (only for GTK Windows)InstallationCurrently, Blighty needs to be built from its source code. The following
installation instructions have been tested on Ubuntu 18.04. If you are using a
different distribution, make sure that you install all the listed dependencies
from your package repository.To install the required dependencies, use the following commandsudo apt install xorg libxinerama-dev libcairo2-dev python3-gi gir1.2-gtk-3.0 gir1.2-glib-2.0To install Blighty from PyPI, use the commandsudo -H python3 -m pip install blighty --upgradeShould you encounter any problems installing Blighty from PyPI, then install it
directly from GitHub with the following command.sudo -H python3 -m pip install git+https://github.com/P403n1x87/blighty.git --upgradeUsageThe official documentation is hosted onReadTheDocs.io. Refer to the code
in theexamplesfolder for some simple examples.This package makes it easy to create transparent windows that you can draw on
withcairo. It takes all the boilerplate code away from you so that you can
just focus on the artwork, pretty much as with Conky.X11 CanvasesThis is the closest to Conky that you can get for the moment, and the
recommended way of using Blighty. Use the following approach to create a window
with the Xlib directly.fromblightyimportCanvasGravityfromblighty.x11importCanvas,start_event_loopclassMyCanvas(Canvas):defon_draw(self,context):# context is an instance of a cairo context.# Refer to the Pycairo documentation.if__name__=="__main__":x,y,width,height=10,10,200,200# Instantiate the canvascanvas=MyCanvas(10,10,width=200,height=200,gravity=CanvasGravity.SOUTH_EAST)# Map it on screencanvas.show()# Start the event loopstart_event_loop()The module implements a basic event loop so that the user interactions with the
canvas can be handled. You can capture key and button presses by implementing
theon_key_pressed(self, keysym, state)andon_button_pressed(self, button, state, x, y)method in your subclass ofCanvas.GTK CanvasesTo create GTK-based canvases you can use theblighty.gtk.Canvasclass, which
is just a subclass ofGtk.Window.fromtimeimportsleepimportblighty.gtkasbclassMyCanvas(b.Canvas):defon_draw(self,widget,cr):# Similar to the X11 case. However, note how# you have access to the whole GTK window# via the `widget` parameter. In principle you# can exploit it to add extra child widgets.# Use wisely.if__name__=="__main__":canvas=MyCanvas(0,0,width=320,height=240)canvas.show_all()b.start_event_loop()AnimationsAnimations can be controlled via theCanvas.intervalattribute. This is the
time in milliseconds that elapses between consecutive redraws of the Canvas.BrushesSince version 1.1.0.Consider the following simple example of a clock widget.fromblightyimportCanvasGravityfromblighty.x11importCanvas,start_event_loopimportdatetimefrommathimportpiasPIclassClock(Canvas):defon_button_pressed(self,button,state,x,y):self.dispose()defhand(self,ctx,angle,length,thickness):ctx.save()ctx.set_source_rgba(1,1,1,1)ctx.set_line_width(thickness)ctx.rotate(angle)ctx.move_to(0,length*.2)ctx.line_to(0,-length)ctx.stroke()ctx.restore()defon_draw(self,ctx):now=datetime.datetime.now()ctx.translate(self.width>>1,self.height>>1)self.hand(ctx,angle=now.second/30*PI,length=(self.height>>1)*.9,thickness=1)mins=now.minute+now.second/60self.hand(ctx,angle=mins/30*PI,length=(self.height>>1)*.8,thickness=3)hours=(now.hour%12)+mins/60self.hand(ctx,angle=hours/6*PI,length=(self.height>>1)*.5,thickness=6)It is clear that thehandmethod would be more appropriate for the instance of
the cairo Contextctx. The coding would be simpler if we could call it asctx.hand.Brushesallow you to re-bind methods from theCanvassubclass to
the cairo context. Import thebrushdecorator fromblightywithfromblightyimportbrushand the use it to decorate thehandmethod. Theselfargument is no longer
necessary, since it will be replaced by the cairo context instance. So the above
code becomesfromblightyimportCanvasGravity,brushfromblighty.x11importCanvas,start_event_loopimportdatetimefrommathimportpiasPIclassClock(Canvas):defon_button_pressed(self,button,state,x,y):self.dispose()@brushdefhand(ctx,angle,length,thickness):ctx.save()ctx.set_source_rgba(1,1,1,1)ctx.set_line_width(thickness)ctx.rotate(angle)ctx.move_to(0,length*.2)ctx.line_to(0,-length)ctx.stroke()ctx.restore()defon_draw(self,ctx):now=datetime.datetime.now()ctx.translate(self.width>>1,self.height>>1)ctx.hand(angle=now.second/30*PI,length=(self.height>>1)*.9,thickness=1)mins=now.minute+now.second/60ctx.hand(angle=mins/30*PI,length=(self.height>>1)*.8,thickness=3)hours=(now.hour%12)+mins/60ctx.hand(angle=hours/6*PI,length=(self.height>>1)*.5,thickness=6)By default, methods of subclasses ofCanvasthat begin withdraw_are
re-bound to the cairo context in theon_drawmethod. So the same as the above
code could be achieved without the use of thebrushdecorator withfromblightyimportCanvasGravityfromblighty.x11importCanvas,start_event_loopimportdatetimefrommathimportpiasPIclassClock(Canvas):defon_button_pressed(self,button,state,x,y):self.dispose()defdraw_hand(ctx,angle,length,thickness):ctx.save()ctx.set_source_rgba(1,1,1,1)ctx.set_line_width(thickness)ctx.rotate(angle)ctx.move_to(0,length*.2)ctx.line_to(0,-length)ctx.stroke()ctx.restore()defon_draw(self,ctx):now=datetime.datetime.now()ctx.translate(self.width>>1,self.height>>1)ctx.draw_hand(angle=now.second/30*PI,length=(self.height>>1)*.9,thickness=1)mins=now.minute+now.second/60ctx.draw_hand(angle=mins/30*PI,length=(self.height>>1)*.8,thickness=3)hours=(now.hour%12)+mins/60ctx.draw_hand(angle=hours/6*PI,length=(self.height>>1)*.5,thickness=6)Brushesare implemented via the classExtendedContext, which is just a
wrapper aroundcairo.Context. The argument passed to theon_drawcallback is
hence an instance of this class. For convenience, it exposes the containing
canvas instance via thecanvasattribute so that it doesn't need to be passed
to the brush method when you need to access some of the canvas attributes (e.g.
its size) or methods.Conky-like GraphsSince version 3.0.0If you really can't do without the Conky look, Blighty offers you Conky-like graphs out of the box.All you have to do is create an instance ofblighty.legacy.Graphby specifying the position and the size of the graph. Optionally, you can also pass ascaleargument, which by default is set to100and defines theyscale of the graph. If you want the graph to auto-scale, usescale=None. You push values to the graph with thepush_valuemethod and draw it on a canvas with thedrawmethod, which requires a Cairo context as argument.LicenseGPLv3.