1#!/usr/local/bin/python3.8
2
3from gi.repository import CinnamonDesktop, GLib, Gtk, Gio, Pango
4
5from util import utils, trackers, settings
6from baseWindow import BaseWindow
7from floating import Floating
8
9MAX_WIDTH = 320
10MAX_WIDTH_LOW_RES = 200
11
12class ClockWidget(Floating, BaseWindow):
13    """
14    ClockWidget displays the time and away message on the screen.
15
16    It is a child of the Stage's GtkOverlay, and its placement is
17    controlled by the overlay's child positioning function.
18
19    When not Awake, it positions itself around all monitors
20    using a timer which randomizes its halign and valign properties
21    as well as its current monitor.
22    """
23    def __init__(self, away_message=None, initial_monitor=0, low_res=False):
24        super(ClockWidget, self).__init__(initial_monitor)
25        self.get_style_context().add_class("clock")
26        self.set_halign(Gtk.Align.START)
27
28        self.set_property("margin", 6)
29
30        self.clock = None
31        self.low_res = low_res
32
33        if not settings.get_show_clock():
34            return
35
36        self.away_message = away_message
37
38        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
39        self.add(box)
40        box.show()
41
42        self.label = Gtk.Label()
43        self.label.show()
44        self.label.set_line_wrap(True)
45        self.label.set_alignment(0.5, 0.5)
46
47        box.pack_start(self.label, True, False, 6)
48
49        self.msg_label = Gtk.Label()
50        self.msg_label.show()
51        self.msg_label.set_line_wrap(True)
52        self.msg_label.set_alignment(0.5, 0.5)
53
54        if self.low_res:
55            self.msg_label.set_max_width_chars(50)
56        else:
57            self.msg_label.set_max_width_chars(80)
58
59        box.pack_start(self.msg_label, True, True, 6)
60
61        self.clock = CinnamonDesktop.WallClock()
62        self.set_clock_format()
63
64        trackers.con_tracker_get().connect(self.clock,
65                                           "notify::clock",
66                                           self.on_clock_changed)
67
68        tz = Gio.File.new_for_path(path="/etc/localtime")
69        self.tz_monitor = tz.monitor_file(0, None)
70
71        trackers.con_tracker_get().connect(self.tz_monitor,
72                                           "changed",
73                                           self.on_tz_changed)
74
75        trackers.con_tracker_get().connect(self,
76                                           "destroy",
77                                           self.on_destroy)
78
79        self.update_clock()
80
81    def set_clock_format(self):
82        date_format = ""
83        time_format = ""
84
85        if settings.get_use_custom_format():
86            date_format = settings.get_custom_date_format()
87            time_format = settings.get_custom_time_format()
88        else:
89            date_format = self.clock.get_default_date_format()
90            time_format = self.clock.get_default_time_format()
91
92            # %l is 12-hr hours, but it adds a space to 0-9, which looks bad here.
93            # The '-' modifier tells the GDateTime formatter not to pad the value.
94            time_format = time_format.replace('%l', '%-l')
95
96        time_font = Pango.FontDescription.from_string(settings.get_time_font())
97        date_font = Pango.FontDescription.from_string(settings.get_date_font())
98
99        if self.low_res:
100            time_size = time_font.get_size() * .66
101            date_size = date_font.get_size() * .66
102            time_font.set_size(int(time_size))
103            date_font.set_size(int(date_size))
104
105        time_format = ('<b><span font_desc=\"%s\" foreground=\"#FFFFFF\">%s</span></b>\n' +             \
106                       '<b><span font_desc=\"%s\" foreground=\"#FFFFFF\">%s</span></b>')                \
107            % (time_font.to_string(), time_format, date_font.to_string(), date_format)
108
109        self.clock.set_format_string(time_format)
110
111    def on_clock_changed(self, clock, pspec):
112        self.update_clock()
113
114    def on_tz_changed(self, monitor, file, other, event):
115        self.update_clock()
116
117    def update_clock(self):
118        default_message = GLib.markup_escape_text (settings.get_default_away_message(), -1)
119        font_message = Pango.FontDescription.from_string(settings.get_message_font())
120
121        if self.low_res:
122            msg_size = font_message.get_size() * .66
123            font_message.set_size(int(msg_size))
124
125        if self.away_message and self.away_message != "":
126            user_name = utils.get_user_display_name()
127            markup = ('<span font_desc=\"{0}\">'
128                + '<b><span foreground=\"#CCCCCC\">{1}</span></b>'
129                + '\n<b><span font_size=\"smaller\" foreground=\"#ACACAC\">  ~ {2}</span></b>'
130                + '</span>\n ').format(
131                     font_message.to_string(), self.away_message, user_name)
132        else:
133            markup = '<b><span font_desc=\"%s\" foreground=\"#CCCCCC\">%s</span></b>\n ' %\
134                     (font_message.to_string(), default_message)
135
136        self.label.set_markup(self.clock.get_clock())
137        self.msg_label.set_markup(markup)
138
139    def set_message(self, msg=""):
140        if not self.clock:
141            return
142
143        self.away_message = msg
144        self.update_clock()
145
146    def on_destroy(self, data=None):
147        trackers.con_tracker_get().disconnect(self.clock,
148                                              "notify::clock",
149                                              self.on_clock_changed)
150
151        trackers.con_tracker_get().disconnect(self.tz_monitor,
152                                              "changed",
153                                              self.on_tz_changed)
154
155        trackers.con_tracker_get().disconnect(self,
156                                              "destroy",
157                                              self.on_destroy)
158
159        self.clock = None
160        self.tz_monitor = None
161