Source code for libqtile.widget.vertical_clock

from datetime import UTC, datetime

from libqtile.confreader import ConfigError
from libqtile.widget import base
from libqtile.widget.clock import Clock


[docs] class VerticalClock(Clock): """ A simple but flexible text-based clock for vertical bars. Unlike the ``Clock`` widget, ``VerticalClock`` will display text horizontally in the bar. """ orientations = base.ORIENTATION_VERTICAL defaults = [ ( "format", ["%H", "%M"], "A list of Python datetime format string. Each string is printed as a separate line.", ), ( "foreground", "fff", "Text colour. A single string will be applied to all fields. " "Alternatively, users can provide a list of strings with each colour being applied to the corresponding text format.", ), ( "fontsize", None, "Font size. A single value will be applied to all fields. " "Alternatively, users can provide a list of sizes with each size being applied to the corresponding text format.", ), ] def __init__(self, **config): Clock.__init__(self, **config) self.add_defaults(VerticalClock.defaults) self.layouts = [] def _to_list(self, value): return [value] * len(self.format) def _configure(self, qtile, bar): base._Widget._configure(self, qtile, bar) if self.fontsize is None: self.fontsize = self._to_list(self.bar.size - self.bar.size / 5) elif isinstance(self.fontsize, int): self.fontsize = self._to_list(self.fontsize) elif not isinstance(self.fontsize, list): raise ConfigError("'fontsize' should be an integer or a list of integers.") elif not all(isinstance(fontsize, int) for fontsize in self.fontsize): raise ConfigError("'fontsize' should be of integers.") elif len(self.fontsize) != len(self.format): raise ConfigError("'fontsize' list should have same number of items as 'format'.") if isinstance(self.foreground, str): self.foreground = self._to_list(self.foreground) elif not isinstance(self.foreground, list): raise ConfigError("'foreground' should be a string or a list of strings.") elif not all(isinstance(foreground, str) for foreground in self.foreground): raise ConfigError("'foreground' list should be of strings.") elif len(self.foreground) != len(self.format): raise ConfigError("'foreground' list should have same number of items as 'format'.") if self.padding is None: self.padding = (sum(self.fontsize) / len(self.fontsize)) // 2 self.layouts = [ self.drawer.textlayout( self.formatted_text, fg, self.font, size, self.fontshadow, markup=self.markup, ) for _, fg, size in zip(self.format, self.foreground, self.fontsize) ] def calculate_length(self): return sum(l.height + self.padding for l in self.layouts) + self.padding def update(self, time): for layout, fmt in zip(self.layouts, self.format): layout.text = time.strftime(fmt) layout.width = self.bar.size self.draw() @property def can_draw(self): return all(layout is not None for layout in self.layouts) # adding .5 to get a proper seconds value because glib could # theoreticaly call our method too early and we could get something # like (x-1).999 instead of x.000 def poll(self): if self.timezone: now = datetime.now(UTC).astimezone(self.timezone) else: now = datetime.now(UTC).astimezone() return now + self.DELTA def draw(self): if not self.can_draw: return offset = self.padding self.drawer.clear(self.background or self.bar.background) for layout in self.layouts: self.drawer.ctx.save() self.drawer.ctx.translate(0, offset) layout.draw(0, 0) offset += layout.height + self.padding self.drawer.ctx.restore() self.draw_at_default_position() def finalize(self): for layout in self.layouts: layout.finalize() layout = None base._Widget.finalize(self)