conf: use shutil.move instead of os.rename for saving
[urk.git] / scripts / theme.py
blob045446a0245a93b0bb3c6b01fbb07c6f40406260
1 import time
3 import windows
4 import widgets
5 import chaninfo
6 import events
7 from conf import conf
9 textareas = {}
10 if 'font' in conf:
11 textareas['font'] = conf['font']
12 if 'bg_color' in conf:
13 textareas['bg'] = conf['bg_color']
14 if 'fg_color' in conf:
15 textareas['fg'] = conf['fg_color']
17 widgets.set_style("view", textareas)
18 widgets.set_style("nicklist", textareas)
20 #copied pretty directly from something that was probably copied from wine sources
21 def RGBtoHSL(r, g, b):
22 maxval = max(r, g, b)
23 minval = min(r, g, b)
25 luminosity = ((maxval + minval) * 240 + 255) // 510
27 if maxval == minval:
28 saturation = 0
29 hue = 160
30 else:
31 delta = maxval - minval
33 if luminosity <= 120:
34 saturation = ((maxval+minval)//2 + delta*240) // (maxval + minval)
35 else:
36 saturation = ((150-maxval-minval)//2 + delta*240) // (150-maxval-minval)
38 #sigh..
39 rnorm = (delta//2 + maxval*40 - r*40)//delta
40 gnorm = (delta//2 + maxval*40 - g*40)//delta
41 bnorm = (delta//2 + maxval*40 - b*40)//delta
43 if r == maxval:
44 hue = bnorm-gnorm
45 elif g == maxval:
46 hue = 80+rnorm-bnorm
47 else:
48 hue = 160+gnorm-rnorm
49 hue = hue % 240
50 return hue, saturation, luminosity
52 #copied from the same place
53 def huetoRGB(hue, mid1, mid2):
54 hue = hue % 240
56 if hue > 160:
57 return mid1
58 elif hue > 120:
59 hue = 160 - hue
60 elif hue > 40:
61 return mid2
62 return ((hue * (mid2 - mid1) + 20) // 40) + mid1
64 #this too
65 def HSLtoRGB(hue, saturation, luminosity):
66 if saturation != 0:
67 if luminosity > 120:
68 mid2 = saturation + luminosity - (saturation * luminosity + 120)//240
69 else:
70 mid2 = ((saturation + 240) * luminosity + 120)//240
72 mid1 = luminosity * 2 - mid2
74 return tuple((huetoRGB(hue+x, mid1, mid2) * 255 + 120) // 240 for x in (80,0,-80))
75 else:
76 value = luminosity * 255 // 240
77 return value, value, value
79 def gethashcolor(string):
80 h = hash(string)
81 rgb = HSLtoRGB(h%241, 100-h//241%61, 90)
82 return "%02x%02x%02x" % rgb
84 #take an event e and trigger the highlight event if necessary
85 def hilight_text(e):
86 if not hasattr(e, 'Highlight'):
87 e.Highlight = []
88 events.trigger('Highlight', e)
90 #hilight own nick
91 def onHighlight(e):
92 lowertext = e.text.lower()
93 for word in conf.get('highlight_words', []) + [e.network.me] + e.network.nicks:
94 lowerword = word.lower()
95 pos = lowertext.find(lowerword, 0)
96 while pos != -1:
97 e.Highlight.append((pos, pos+len(word)))
98 pos = lowertext.find(lowerword, pos+1)
100 def prefix(e):
101 return time.strftime(conf.get('timestamp', ''))
103 def getsourcecolor(e):
104 address = getattr(e, "address", "")
105 if address:
106 if e.network.me == e.source:
107 e.network._my_address = address
108 elif e.network.me == e.source:
109 address = getattr(e.network, "_my_address", "")
110 if '@' in address:
111 address = address.split('@')[1]
112 if not address:
113 address = e.source
114 return "\x04%s" % gethashcolor(address)
116 def format_source(e):
117 highlight = getattr(e, "Highlight", "") and '\x02' or ''
118 return "%s\x04%s%s" % (highlight, getsourcecolor(e), e.source)
120 def format_info_source(e):
121 if e.source == e.network.me:
122 return "\x04%sYou" % (getsourcecolor(e))
123 else:
124 return "\x04%s%s" % (getsourcecolor(e), e.source)
126 def address(e):
127 #if e.source != e.network.me:
128 # return "%s " % info_in_brackets(e.address)
129 #else:
130 # return ""
131 return ""
133 def text(e):
134 if e.text:
135 #return " %s" % info_in_brackets(e.text)
136 return ": \x0F%s" % e.text
137 else:
138 return ""
140 def info_in_brackets(text):
141 return "(\x044881b6%s\x0F)" % text
143 def pretty_time(secs):
144 times = (
145 #("years", "year", 31556952),
146 ("weeks", "week", 604800),
147 ("days", "day", 86400),
148 ("hours", "hour", 3600),
149 ("minutes", "minute", 60),
150 ("seconds", "second", 1),
152 if secs == 0:
153 return "0 seconds"
154 result = ""
155 for plural, singular, amount in times:
156 n, secs = divmod(secs, amount)
157 if n == 1:
158 result = result + " %s %s" % (n, singular)
159 elif n:
160 result = result + " %s %s" % (n, plural)
161 return result[1:]
163 def onText(e):
164 hilight_text(e)
165 color = getsourcecolor(e)
166 to_write = prefix(e)
167 if e.network.me == e.target: # this is a pm
168 if e.window.id == e.network.norm_case(e.source):
169 to_write += "\x02<\x0F%s\x0F\x02>\x0F " % (format_source(e))
170 else:
171 to_write += "\x02*\x0F%s\x0F\x02*\x0F " % (format_source(e))
172 else:
173 if e.window.id == e.network.norm_case(e.target):
174 to_write += "\x02<\x0F%s\x0F\x02>\x0F " % (format_source(e))
175 else:
176 to_write += "\x02<\x0F%s:%s\x0F\x02>\x0F " % (format_source(e), e.target)
177 to_write += e.text
179 if e.Highlight:
180 e.window.write(to_write, widgets.HILIT)
181 else:
182 e.window.write(to_write, widgets.TEXT)
184 def onOwnText(e):
185 color = getsourcecolor(e)
186 to_write = prefix(e)
187 if e.window.id == e.network.norm_case(e.target):
188 to_write += "\x02<\x0F%s\x0F\x02>\x0F %s" % (format_source(e), e.text)
189 else:
190 to_write += "%s->\x0F \x02*\x0F%s\x0F\x02*\x0F %s" % (color, e.target, e.text)
192 e.window.write(to_write)
194 def onAction(e):
195 hilight_text(e)
196 color = color = getsourcecolor(e)
197 to_write = "%s\x02*\x0F %s\x0F %s" % (prefix(e), format_source(e), e.text)
199 if e.Highlight:
200 e.window.write(to_write, widgets.HILIT)
201 else:
202 e.window.write(to_write, widgets.TEXT)
204 def onOwnAction(e):
205 color = getsourcecolor(e)
206 to_write = "%s\x02*\x0F %s\x0F %s" % (prefix(e), format_source(e), e.text)
208 e.window.write(to_write)
210 def onNotice(e):
211 hilight_text(e)
212 color = getsourcecolor(e)
213 to_write = prefix(e)
214 if e.network.me == e.target: # this is a pm
215 to_write += "\x02-\x0F%s\x0F\x02-\x0F " % (format_source(e))
216 else:
217 to_write += "\x02-\x0F%s:%s\x0F\x02-\x0F " % (format_source(e), e.target)
218 to_write += e.text
220 e.window.write(to_write, (e.Highlight and widgets.HILIT) or widgets.TEXT)
222 def onOwnNotice(e):
223 color = getsourcecolor(e)
224 to_write = "%s-> \x02-\x02%s\x0F\x02-\x0F %s" % (prefix(e), e.target, e.text)
226 e.window.write(to_write)
228 def onCtcp(e):
229 color = getsourcecolor(e)
230 to_write = "%s\x02[\x02%s\x0F\x02]\x0F %s" % (prefix(e), format_source(e), e.text)
232 if not e.quiet:
233 e.window.write(to_write)
235 def onCtcpReply(e):
236 color = getsourcecolor(e)
237 to_write = "%s%s--- %s reply from %s:\x0F %s" % (prefix(e), color, e.name.capitalize(), format_source(e), ' '.join(e.args))
239 window = windows.manager.get_active()
240 if window.network != e.network:
241 window = windows.get_default(e.network)
242 window.write(to_write, widgets.TEXT)
244 def onJoin(e):
245 if e.source == e.network.me:
246 to_write = "%s%s %sjoin %s" % (prefix(e), format_info_source(e), address(e), e.target)
247 else:
248 to_write = "%s%s %sjoins %s" % (prefix(e), format_info_source(e), address(e), e.target)
250 e.window.write(to_write)
252 def onPart(e):
253 if e.source == e.network.me:
254 to_write = "%s%s leave %s%s" % (prefix(e), format_info_source(e), e.target, text(e))
255 else:
256 to_write = "%s%s leaves %s%s" % (prefix(e), format_info_source(e), e.target, text(e))
258 e.window.write(to_write)
260 def onKick(e):
261 if e.source == e.network.me:
262 to_write = "%s%s kick %s%s" % (prefix(e), format_info_source(e), e.target, text(e))
263 else:
264 to_write = "%s%s kicks %s%s" % (prefix(e), format_info_source(e), e.target, text(e))
266 e.window.write(to_write, (e.target == e.network.me and widgets.HILIT) or widgets.EVENT)
268 def onMode(e):
269 if e.source == e.network.me:
270 to_write = "%s%s set mode:\x0F %s" % (prefix(e), format_info_source(e), e.text)
271 else:
272 to_write = "%s%s sets mode:\x0F %s" % (prefix(e), format_info_source(e), e.text)
274 e.window.write(to_write)
276 def onQuit(e):
277 to_write = "%s%s leaves%s" % (prefix(e), format_info_source(e), text(e))
279 for channame in chaninfo.channels(e.network):
280 if chaninfo.ison(e.network, channame, e.source):
281 window = windows.get(windows.ChannelWindow, e.network, channame)
282 if window:
283 window.write(to_write)
285 def onNick(e):
286 color = getsourcecolor(e)
287 if e.source == e.network.me:
288 to_write = "%s%sYou are now known as %s" % (prefix(e), color, e.target)
289 else:
290 to_write = "%s%s%s is now known as %s" % (prefix(e), color, e.source, e.target)
292 if e.source == e.network.me:
293 for window in windows.get_with(network=e.network):
294 window.write(to_write)
295 else:
296 for channame in chaninfo.channels(e.network):
297 if chaninfo.ison(e.network,channame,e.source):
298 window = windows.get(windows.ChannelWindow, e.network, channame)
299 if window:
300 window.write(to_write)
302 def onTopic(e):
303 if e.source == e.network.me:
304 to_write = "%s%s set topic:\x0F %s" % (prefix(e), format_info_source(e), e.text)
305 else:
306 to_write = "%s%s sets topic:\x0F %s" % (prefix(e), format_info_source(e), e.text)
308 e.window.write(to_write)
310 def onRaw(e):
311 if not e.quiet:
312 if e.msg[1].isdigit():
313 if e.msg[1] == '332':
314 window = windows.get(windows.ChannelWindow, e.network, e.msg[3]) or e.window
315 window.write(
316 "%sTopic on %s is: %s" %
317 (prefix(e), e.msg[3], e.text)
320 elif e.msg[1] == '333':
321 window = windows.get(windows.ChannelWindow, e.network, e.msg[3]) or e.window
322 window.write(
323 "%sTopic on %s set by %s at time %s" %
324 (prefix(e), e.msg[3], e.msg[4], time.ctime(int(e.msg[5])))
327 elif e.msg[1] == '329': #RPL_CREATIONTIME
328 pass
330 elif e.msg[1] == '311': #RPL_WHOISUSER
331 e.window.write("* %s is %s@%s * %s" % (e.msg[3], e.msg[4], e.msg[5], e.msg[7]))
333 elif e.msg[1] == '312': #RPL_WHOISSERVER
334 e.window.write("* %s on %s (%s)" % (e.msg[3], e.msg[4], e.msg[5]))
336 elif e.msg[1] == '317': #RPL_WHOISIDLE
337 e.window.write("* %s has been idle for %s" % (e.msg[3], pretty_time(int(e.msg[4]))))
338 if e.msg[5].isdigit():
339 e.window.write("* %s signed on %s" % (e.msg[3], time.ctime(int(e.msg[5]))))
341 elif e.msg[1] == '319': #RPL_WHOISCHANNELS
342 e.window.write("* %s on channels: %s" % (e.msg[3], e.msg[4]))
344 elif e.msg[1] == '330': #RPL_WHOISACCOUNT
345 #this appears to conflict with another raw, so if there's anything weird about it,
346 # we fall back on the default
347 if len(e.msg) == 6 and not e.msg[4].isdigit() and not e.msg[5].isdigit():
348 e.window.write("* %s %s %s" % (e.msg[3], e.msg[5], e.msg[4]))
349 else:
350 e.window.write("* %s" % ' '.join(e.msg[3:]))
352 else:
353 e.window.write("* %s" % ' '.join(e.msg[3:]))
354 elif e.msg[1] == 'ERROR':
355 e.window.write("Error: %s" % e.text)
357 def onDisconnect(e):
358 to_write = '%s* Disconnected' % prefix(e)
359 if e.error:
360 to_write += ' (%s)' % e.error
362 for window in windows.get_with(network=e.network):
363 if isinstance(window, windows.StatusWindow):
364 window.write(to_write, widgets.TEXT)
365 else:
366 window.write(to_write, widgets.EVENT)