Added GPL license
[pedometerwidget] / pedometer_widget_home.py
1 #Pedometer Home Widget
2 #Author: Mirestean Andrei < andrei.mirestean at gmail.com >
3 #
4 #This program is free software: you can redistribute it and/or modify
5 #it under the terms of the GNU General Public License as published by
6 #the Free Software Foundation, either version 3 of the License, or
7 #(at your option) any later version.
8 #
9 #This program is distributed in the hope that it will be useful,
10 #but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 #GNU General Public License for more details.
13 #
14 #You should have received a copy of the GNU General Public License
15 #along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17 import gtk
18 import cairo
19 import hildondesktop
20 import gobject
21 import os
22 import time
23 import hildon
24 import gnome.gconf as gconf
25 from threading import Thread
26
27 #gobject.threads_init()
28 #gtk.gdk.threads_init()
29
30 PATH="/apps/pedometerhomewidget"
31 COUNTER=PATH+"/counter"
32 TIMER=PATH+"/timer"
33 MODE=PATH+"/mode"
34 HEIGHT=PATH+"/height"
35 UNIT=PATH+"/unit"
36 ASPECT=PATH+"/aspect"
37 LOGGING=PATH+"/logging"
38
39 ICONSPATH = "/opt/pedometerhomewidget/"
40
41 class PedoIntervalCounter:
42     MIN_THRESHOLD = 500
43     MIN_TIME_STEPS = 0.5
44     x = []
45     y = []
46     z = []
47     t = []
48
49     #TODO: check if last detected step is at the end of the interval
50
51     def __init__(self, coords, tval):
52         self.x = coords[0]
53         self.y = coords[1]
54         self.z = coords[2]
55         self.t = tval
56
57     def setThreshold(self, value):
58         self.MIN_THRESHOLD = value
59
60     def setTimeSteps(self, value):
61         self.MIN_TIME_STEPS = value
62
63     def calc_mean(self, vals):
64         sum = 0
65         for i in vals:
66             sum+=i
67         if len(vals) > 0:
68             return sum / len(vals)
69         return 0
70
71     def calc_stdev(self, vals):
72         rez = 0
73         mean = self.calc_mean(vals)
74         for i in vals:
75             rez+=pow(abs(mean-i),2)
76         return math.sqrt(rez/len(vals))
77
78     def calc_threshold(self, vals):
79         vmax = max(vals)
80         vmin = min(vals)
81         mean = self.calc_mean(vals)
82         threshold = max (abs(mean-vmax), abs(mean-vmin))
83         return threshold
84
85     def count_steps(self, vals, t):
86         threshold = self.MIN_THRESHOLD
87         mean = self.calc_mean(vals)
88         cnt = 0
89
90         i=0
91         while i < len(vals):
92             if abs(vals[i] - mean) > threshold:
93                 cnt+=1
94                 ntime = t[i] + 0.5
95                 while i < len(vals) and t[i] < ntime:
96                     i+=1
97             i+=1
98         return cnt
99
100     def get_best_values(self, x, y, z):
101         dev1 = self.calc_stdev(x)
102         dev2 = self.calc_stdev(y)
103         dev3 = self.calc_stdev(z)
104         dev_max = max(dev1, dev2, dev3)
105
106         if ( abs(dev1 - dev_max ) < 0.001):
107             logger.info("X chosen as best axis, stdev %f" % dev1)
108             return x
109         elif (abs(dev2 - dev_max) < 0.001):
110             logger.info("Y chosen as best axis, stdev %f" % dev2)
111             return y
112         else:
113             logger.info("Z chosen as best axis, stdev %f" % dev3)
114             return z
115
116     def number_steps(self):
117         vals = self.get_best_values(self.x, self.y, self.z)
118         return self.count_steps(vals, self.t)
119
120 class PedoCounter(Thread):
121     COORD_FNAME = "/sys/class/i2c-adapter/i2c-3/3-001d/coord"
122     COORD_FNAME_SDK = "/home/andrei/pedometer-widget-0.1/date.txt"
123     LOGFILE = "/home/user/log_pedometer"
124     COORD_GET_INTERVAL = 0.01
125     COUNT_INTERVAL = 5
126
127     STEP_LENGTH = 0.7
128
129     MIN_THRESHOLD = 500
130     MIN_TIME_STEPS = 0.5
131
132     counter = 0
133     stop_requested = False
134     update_function = None
135     logging = False
136
137     mode = 0
138
139     def __init__(self, update_function = None):
140         Thread.__init__(self)
141         if not os.path.exists(self.COORD_FNAME):
142             self.COORD_FNAME = self.COORD_FNAME_SDK
143
144         self.update_function = update_function
145
146     def set_mode(self, mode):
147         #runnig, higher threshold to prevent fake steps
148         self.mode = mode
149         if mode == 1:
150             self.MIN_THRESHOLD = 650
151             self.MIN_TIME_STEPS = 0.35
152         #walking
153         else:
154             self.MIN_THRESHOLD = 500
155             self.MIN_TIME_STEPS = 0.5
156
157     def set_logging(self, value):
158         self.logging = value
159
160     #set height, will affect the distance
161     def set_height(self, height_interval):
162         if height_interval == 0:
163             self.STEP_LENGTH = 0.59
164         elif height_interval == 1:
165             self.STEP_LENGTH = 0.64
166         elif height_interval == 2:
167             self.STEP_LENGTH = 0.71
168         elif height_interval == 3:
169             self.STEP_LENGTH = 0.77
170         elif height_interval == 4:
171             self.STEP_LENGTH = 0.83
172         #increase step length if RUNNING
173         if self.mode == 1:
174             self.STEP_LENGTH *= 1.45
175
176     def get_rotation(self):
177         f = open(self.COORD_FNAME, 'r')
178         coords = [int(w) for w in f.readline().split()]
179         f.close()
180         return coords
181
182     def reset_counter(self):
183         counter = 0
184
185     def get_counter(self):
186         return counter
187
188     def start_interval(self):
189         logger.info("New interval started")
190         stime = time.time()
191         t=[]
192         coords = [[], [], []]
193         while not self.stop_requested and (len(t) == 0 or t[-1] < 5):
194             x,y,z = self.get_rotation()
195             coords[0].append(int(x))
196             coords[1].append(int(y))
197             coords[2].append(int(z))
198             now = time.time()-stime
199             if self.logging:
200                 self.file.write("%d %d %d %f\n" %(coords[0][-1], coords[1][-1], coords[2][-1], now))
201
202             t.append(now)
203             time.sleep(self.COORD_GET_INTERVAL)
204         pic = PedoIntervalCounter(coords, t)
205         cnt = pic.number_steps()
206
207         logger.info("Number of steps detected for last interval %d, number of coords: %d" % (cnt, len(t)))
208
209         self.counter += cnt
210         logger.info("Total number of steps : %d" % self.counter)
211         return cnt
212
213     def request_stop(self):
214         self.stop_requested = True
215
216     def run(self):
217         logger.info("Thread started")
218         if self.logging:
219             fname = "%d_%d_%d_%d_%d_%d" % time.localtime()[0:6]
220             self.file = open(self.LOGFILE + fname + ".txt", "w")
221
222         while 1 and not self.stop_requested:
223             last_cnt = self.start_interval()
224             if self.update_function is not None:
225                 gobject.idle_add(self.update_function, self.counter, last_cnt)
226
227         if self.logging:
228             self.file.close()
229
230         logger.info("Thread has finished")
231
232     def get_distance(self, steps=None):
233         if steps == None:
234             steps = self.counter
235         return self.STEP_LENGTH * steps;
236
237 class CustomButton(hildon.Button):
238     def __init__(self, icon):
239         hildon.Button.__init__(self, gtk.HILDON_SIZE_AUTO_WIDTH, hildon.BUTTON_ARRANGEMENT_VERTICAL)
240         self.icon = icon
241         self.set_size_request(int(32*1.4), int(30*1.0))
242         self.retval = self.connect("expose_event", self.expose)
243
244     def set_icon(self, icon):
245         self.icon = icon
246
247     def expose(self, widget, event):
248         self.context = widget.window.cairo_create()
249         self.context.rectangle(event.area.x, event.area.y,
250                             event.area.width, event.area.height)
251
252         self.context.clip()
253         rect = self.get_allocation()
254         self.context.rectangle(rect.x, rect.y, rect.width, rect.height)
255         self.context.set_source_rgba(1, 1, 1, 0)
256
257         style = self.rc_get_style()
258         color = style.lookup_color("DefaultBackgroundColor")
259         if self.state == gtk.STATE_ACTIVE:
260             style = self.rc_get_style()
261             color = style.lookup_color("SelectionColor")
262             self.context.set_source_rgba (color.red/65535.0, color.green/65335.0, color.blue/65535.0, 0.75);
263         self.context.fill()
264
265         #img = cairo.ImageSurface.create_from_png(self.icon)
266
267         #self.context.set_source_surface(img)
268         #self.context.set_source_surface(img, rect.width/2 - img.get_width() /2, 0)
269         img = gtk.Image()
270         img.set_from_file(self.icon)
271         buf = img.get_pixbuf()
272         buf =  buf.scale_simple(int(32 * 1.5), int(30 * 1.5), gtk.gdk.INTERP_BILINEAR)
273
274         self.context.set_source_pixbuf(buf, rect.x+(event.area.width/2-15)-8, rect.y+1)
275         self.context.scale(200,200)
276         self.context.paint()
277
278         return self.retval
279
280 class PedometerHomePlugin(hildondesktop.HomePluginItem):
281     button = None
282
283     #labels for current steps
284     labels = ["timer", "count", "dist", "avgSpeed"]
285     #labelsC = { "timer" : None, "count" : None, "dist" : None, "avgSpeed" : None }
286
287     #labels for all time steps
288     #labelsT = { "timer" : None, "count" : None, "dist" : None, "avgSpeed" : None }
289     labelsC = {}
290     labelsT = {}
291
292     pedometer = None
293     startTime = None
294
295     totalCounter = 0
296     totalTime = 0
297     mode = 0
298     height = 0
299     unit = 0
300
301     counter = 0
302     time = 0
303     aspect = 0
304     logging = False
305
306     def __init__(self):
307         gtk.gdk.threads_init()
308         #gobject.threads_init()
309         hildondesktop.HomePluginItem.__init__(self)
310
311         self.client = gconf.client_get_default()
312         try:
313             self.totalCounter = self.client.get_int(COUNTER)
314             self.totalTime = self.client.get_int(TIMER)
315             self.mode = self.client.get_int(MODE)
316             self.height = self.client.get_int(HEIGHT)
317             self.unit = self.client.get_int(UNIT)
318             self.aspect = self.client.get_int(ASPECT)
319             self.logging = self.client.get_bool(LOGGING)
320         except:
321             self.client.set_int(COUNTER, 0)
322             self.client.set_int(TIMER, 0)
323             self.client.set_int(MODE, 0)
324             self.client.set_int(HEIGHT, 0)
325             self.client.set_int(UNIT, 0)
326             self.client.set_int(ASPECT, 0)
327             self.client.set_bool(LOGGING, False)
328
329         self.pedometer = PedoCounter(self.update_values)
330         self.pedometer.set_mode(self.mode)
331         self.pedometer.set_height(self.height)
332
333         #self.button = gtk.Button("Start")
334         self.button = CustomButton(ICONSPATH + "play.png")
335         self.button.connect("clicked", self.button_clicked)
336
337         self.create_labels(self.labelsC)
338         self.create_labels(self.labelsT)
339
340         self.update_ui_values(self.labelsC, 0, 0)
341         self.update_ui_values(self.labelsT, self.totalTime, self.totalCounter)
342
343         mainHBox = gtk.HBox(spacing=1)
344
345         descVBox = gtk.VBox(spacing=1)
346         descVBox.add(self.new_label_heading())
347         descVBox.add(self.new_label_heading("Time:"))
348         descVBox.add(self.new_label_heading("Steps:"))
349         descVBox.add(self.new_label_heading("Distance:"))
350         descVBox.add(self.new_label_heading("Avg Speed:"))
351
352         currentVBox = gtk.VBox(spacing=1)
353         currentVBox.add(self.new_label_heading("Current"))
354         currentVBox.add(self.labelsC["timer"])
355         currentVBox.add(self.labelsC["count"])
356         currentVBox.add(self.labelsC["dist"])
357         currentVBox.add(self.labelsC["avgSpeed"])
358         self.currentBox = currentVBox
359
360         totalVBox = gtk.VBox(spacing=1)
361         totalVBox.add(self.new_label_heading("Total"))
362         totalVBox.add(self.labelsT["timer"])
363         totalVBox.add(self.labelsT["count"])
364         totalVBox.add(self.labelsT["dist"])
365         totalVBox.add(self.labelsT["avgSpeed"])
366         self.totalBox = totalVBox
367
368         buttonVBox = gtk.VBox(spacing=1)
369         buttonVBox.add(self.new_label_heading(""))
370         buttonVBox.add(self.button)
371         buttonVBox.add(self.new_label_heading(""))
372
373         mainHBox.add(buttonVBox)
374         mainHBox.add(descVBox)
375         mainHBox.add(currentVBox)
376         mainHBox.add(totalVBox)
377
378         self.mainhbox = mainHBox
379
380         mainHBox.show_all()
381         self.add(mainHBox)
382         self.update_aspect()
383
384         self.connect("unrealize", self.close_requested)
385         self.set_settings(True)
386         self.connect("show-settings", self.show_settings)
387
388     def new_label_heading(self, title=""):
389         l = gtk.Label(title)
390         hildon.hildon_helper_set_logical_font(l, "SmallSystemFont")
391         return l
392
393     def create_labels(self, new_labels):
394         for label in self.labels:
395             l = gtk.Label()
396             hildon.hildon_helper_set_logical_font(l, "SmallSystemFont")
397             hildon.hildon_helper_set_logical_color(l, gtk.RC_FG, gtk.STATE_NORMAL, "ActiveTextColor")
398             new_labels[label] = l
399
400     def update_aspect(self):
401         if self.aspect == 0:
402             self.currentBox.show_all()
403             self.totalBox.show_all()
404         elif self.aspect == 1:
405             self.currentBox.show_all()
406             self.totalBox.hide_all()
407         else:
408             self.currentBox.hide_all()
409             self.totalBox.show_all()
410
411     def update_ui_values(self, labels, timer, steps):
412         def get_str_distance(meters):
413             if meters > 1000:
414                 if self.unit == 0:
415                     return "%.2f km" % (meters/1000)
416                 else:
417                     return "%.2f mi" % (meters/1609.344)
418             else:
419                 if self.unit == 0:
420                     return "%d m" % meters
421                 else:
422                     return "%d ft" % int(meters*3.2808)
423
424         def get_avg_speed(timer, dist):
425             suffix = ""
426             conv = 0
427             if self.unit:
428                 suffix = "mi/h"
429                 conv = 2.23693629
430             else:
431                 suffix = "km/h"
432                 conv = 3.6
433
434             if timer == 0:
435                 return "N/A " + suffix
436             speed = 1.0 *dist / timer
437             #convert from meters per second to km/h or mi/h
438             speed *= conv
439             return "%.2f %s" % (speed, suffix)
440
441         tdelta = timer
442         hours = int(tdelta / 3600)
443         tdelta -= 3600 * hours
444         mins = int(tdelta / 60)
445         tdelta -= 60 * mins
446         secs = int(tdelta)
447
448         strtime = "%.2d:%.2d:%.2d" % ( hours, mins, secs)
449
450         labels["timer"].set_label(strtime)
451         labels["count"].set_label(str(steps))
452
453         dist = self.pedometer.get_distance(steps)
454
455         labels["dist"].set_label(get_str_distance(dist))
456         labels["avgSpeed"].set_label(get_avg_speed(timer, dist))
457
458     def update_current(self):
459         self.update_ui_values(self.labelsC, self.time, self.counter)
460
461     def update_total(self):
462         self.update_ui_values(self.labelsT, self.totalTime, self.totalCounter)
463
464     def show_settings(self, widget):
465         def reset_total_counter(arg):
466             widget.totalCounter = 0
467             widget.totalTime = 0
468             widget.update_total()
469             hildon.hildon_banner_show_information(self,"None", "Total counter was resetted")
470
471         def selector_changed(selector, data):
472             widget.mode = selector.get_active(0)
473             widget.client.set_int(MODE, widget.mode)
474             widget.pedometer.set_mode(widget.mode)
475             widget.pedometer.set_height(widget.height)
476             widget.update_current()
477             widget.update_total()
478
479         def selectorH_changed(selector, data):
480             widget.height = selectorH.get_active(0)
481             widget.client.set_int(HEIGHT, widget.height)
482             widget.pedometer.set_height(widget.height)
483             widget.update_current()
484             widget.update_total()
485
486
487         def selectorUnit_changed(selector, data):
488             widget.unit = selectorUnit.get_active(0)
489             widget.client.set_int(UNIT, widget.unit)
490             widget.update_current()
491             widget.update_total()
492
493         def selectorUI_changed(selector, data):
494             widget.aspect = selectorUI.get_active(0)
495             widget.client.set_int(ASPECT, widget.aspect)
496             widget.update_aspect()
497
498         def logButton_changed(checkButton):
499             widget.logging = checkButton.get_active()
500             widget.client.set_bool(LOGGING, widget.logging)
501
502         dialog = gtk.Dialog()
503         dialog.set_transient_for(self)
504         dialog.set_title("Settings")
505
506         dialog.add_button("OK", gtk.RESPONSE_OK)
507         button = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
508         button.set_title("Reset total counter")
509         button.set_alignment(0, 0.8, 1, 1)
510         button.connect("clicked", reset_total_counter)
511
512         selector = hildon.TouchSelector(text=True)
513         selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
514         selector.append_text("Walk")
515         selector.append_text("Run")
516         selector.connect("changed", selector_changed)
517
518         modePicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
519         modePicker.set_alignment(0.0, 0.5, 1.0, 1.0)
520         modePicker.set_title("Select mode")
521         modePicker.set_selector(selector)
522         modePicker.set_active(widget.mode)
523
524         selectorH = hildon.TouchSelector(text=True)
525         selectorH.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
526         selectorH.append_text("< 1.50 m")
527         selectorH.append_text("1.50 - 1.65 m")
528         selectorH.append_text("1.66 - 1.80 m")
529         selectorH.append_text("1.81 - 1.95 m")
530         selectorH.append_text(" > 1.95 m")
531         selectorH.connect("changed", selectorH_changed)
532
533         heightPicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
534         heightPicker.set_alignment(0.0, 0.5, 1.0, 1.0)
535         heightPicker.set_title("Select height")
536         heightPicker.set_selector(selectorH)
537         heightPicker.set_active(widget.height)
538
539         selectorUnit = hildon.TouchSelector(text=True)
540         selectorUnit.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
541         selectorUnit.append_text("Metric (km)")
542         selectorUnit.append_text("English (mi)")
543         selectorUnit.connect("changed", selectorUnit_changed)
544
545         unitPicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
546         unitPicker.set_alignment(0.0, 0.5, 1.0, 1.0)
547         unitPicker.set_title("Units")
548         unitPicker.set_selector(selectorUnit)
549         unitPicker.set_active(widget.unit)
550
551         selectorUI = hildon.TouchSelector(text=True)
552         selectorUI = hildon.TouchSelector(text=True)
553         selectorUI.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
554         selectorUI.append_text("Show current + total")
555         selectorUI.append_text("Show only current")
556         selectorUI.append_text("Show only total")
557         selectorUI.connect("changed", selectorUI_changed)
558
559         UIPicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
560         UIPicker.set_alignment(0.0, 0.5, 1.0, 1.0)
561         UIPicker.set_title("Widget aspect")
562         UIPicker.set_selector(selectorUI)
563         UIPicker.set_active(widget.aspect)
564
565         logButton = hildon.CheckButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT)
566         logButton.set_label("Log data")
567         logButton.set_active(widget.logging)
568         logButton.connect("toggled", logButton_changed)
569
570         pan_area = hildon.PannableArea()
571         vbox = gtk.VBox()
572         vbox.add(button)
573         vbox.add(modePicker)
574         vbox.add(heightPicker)
575         vbox.add(unitPicker)
576         vbox.add(UIPicker)
577         vbox.add(logButton)
578
579         pan_area.add_with_viewport(vbox)
580         pan_area.set_size_request(-1, 600)
581         dialog.vbox.add(pan_area)
582         dialog.show_all()
583         response = dialog.run()
584         #hildon.hildon_banner_show_information(self, "None", "You have to Stop/Start the counter to apply the new settings")
585         dialog.destroy()
586
587     def close_requested(self, widget):
588         if self.pedometer is None:
589             return
590
591         self.pedometer.request_stop()
592         if self.pedometer.isAlive():
593             self.pedometer.join()
594
595     def update_values(self, totalCurent, lastInterval):
596         self.totalCounter += lastInterval
597         self.counter = totalCurent
598
599         tdelta = time.time() - self.time - self.startTime
600         self.time += tdelta
601         self.totalTime += tdelta
602
603         self.update_current()
604         self.update_total()
605
606     def button_clicked(self, button):
607         if self.pedometer is not None and self.pedometer.isAlive():
608             #counter is running
609             self.pedometer.request_stop()
610             self.pedometer.join()
611             self.client.set_int(COUNTER, self.totalCounter)
612             self.client.set_int(TIMER, int(self.totalTime))
613             #self.button.set_label("Start")
614             self.button.set_icon(ICONSPATH + "play.png")
615         else:
616             self.pedometer = PedoCounter(self.update_values)
617             self.pedometer.set_mode(self.mode)
618             self.pedometer.set_height(self.height)
619             self.pedometer.set_logging(self.logging)
620
621             self.time = 0
622             self.counter = 0
623
624             self.update_current()
625
626             self.pedometer.start()
627             self.startTime = time.time()
628             #self.button.set_label("Stop")
629             self.button.set_icon(ICONSPATH + "stop.png")
630
631     def do_expose_event(self, event):
632         cr = self.window.cairo_create()
633         cr.region(event.window.get_clip_region())
634         cr.clip()
635         #cr.set_source_rgba(0.4, 0.64, 0.564, 0.5)
636         style = self.rc_get_style()
637         color = style.lookup_color("DefaultBackgroundColor")
638         cr.set_source_rgba (color.red/65535.0, color.green/65335.0, color.blue/65535.0, 0.75);
639
640         radius = 5
641         width = self.allocation.width
642         height = self.allocation.height
643
644         x = self.allocation.x
645         y = self.allocation.y
646
647         cr.move_to(x+radius, y)
648         cr.line_to(x + width - radius, y)
649         cr.curve_to(x + width - radius, y, x + width, y, x + width, y + radius)
650         cr.line_to(x + width, y + height - radius)
651         cr.curve_to(x + width, y + height - radius, x + width, y + height, x + width - radius, y + height)
652         cr.line_to(x + radius, y + height)
653         cr.curve_to(x + radius, y + height, x, y + height, x, y + height - radius)
654         cr.line_to(x, y + radius)
655         cr.curve_to(x, y + radius, x, y, x + radius, y)
656
657         cr.set_operator(cairo.OPERATOR_SOURCE)
658         cr.fill_preserve()
659
660         color = style.lookup_color("ActiveTextColor")
661         cr.set_source_rgba (color.red/65535.0, color.green/65335.0, color.blue/65535.0, 0.5);
662         cr.set_line_width(1)
663         cr.stroke()
664
665         hildondesktop.HomePluginItem.do_expose_event(self, event)
666
667     def do_realize(self):
668         screen = self.get_screen()
669         self.set_colormap(screen.get_rgba_colormap())
670         self.set_app_paintable(True)
671         hildondesktop.HomePluginItem.do_realize(self)
672
673 hd_plugin_type = PedometerHomePlugin
674
675 # The code below is just for testing purposes.
676 # It allows to run the widget as a standalone process.
677 if __name__ == "__main__":
678     import gobject
679     gobject.type_register(hd_plugin_type)
680     obj = gobject.new(hd_plugin_type, plugin_id="plugin_id")
681     obj.show_all()
682     gtk.main()
683
684 ############### old pedometer.py ###
685 import math
686 import logging
687
688 from threading import Thread
689
690 logger = logging.getLogger("pedometer")
691 logger.setLevel(logging.INFO)
692
693 ch = logging.StreamHandler()
694 formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
695 ch.setFormatter(formatter)
696 logger.addHandler(ch)
697