def __init__(self, lat=None, lng=None, radius=500): self.lat = lat self.lng = lng self.radius = radius self.zoom = 17 self.ftid = None self.mercator = GlobalMercator(tileSize=256) self.gmm = GMapMetadata(zoom=self.zoom) Notify.init("bus-notify")
class BusNotify: def __init__(self, lat=None, lng=None, radius=500): self.lat = lat self.lng = lng self.radius = radius self.zoom = 17 self.ftid = None self.mercator = GlobalMercator(tileSize=256) self.gmm = GMapMetadata(zoom=self.zoom) Notify.init("bus-notify") def main(self): win = Gtk.Window(title="Bus Notify") win.set_border_width(10) vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6) self.title_label = Gtk.Label(label="Select a nearby bus stop.", justify=Gtk.Justification.LEFT) vbox.pack_start(self.title_label, False, False, 0) self.bus_stops = self.proximity_search(self.lat, self.lng, self.radius, self.zoom) bus_list = Gtk.ListStore(str, str) for ftid, stop in self.bus_stops.iteritems(): bus_list.append([str(ftid), str(stop["caption"])]) self.combo_bus_stops = Gtk.ComboBox.new_with_model(bus_list) renderer_text = Gtk.CellRendererText() self.combo_bus_stops.pack_start(renderer_text, True) self.combo_bus_stops.add_attribute(renderer_text, "text", 1) self.combo_bus_stops.connect("changed", self.on_select_stop) vbox.pack_start(self.combo_bus_stops, False, False, 0) self.stop_assoc_lines = Gtk.ListStore(int, str) self.combo_lines = Gtk.ComboBox.new_with_model(self.stop_assoc_lines) renderer_text = Gtk.CellRendererText() self.combo_lines.pack_start(renderer_text, True) self.combo_lines.add_attribute(renderer_text, "text", 1) self.combo_lines.connect("changed", self.on_select_line) vbox.pack_start(self.combo_lines, False, False, 0) win.add(vbox) win.connect("delete-event", Gtk.main_quit) win.show_all() Gtk.main() def on_select_stop(self, combo): combo_iter = combo.get_active_iter() if combo_iter != None: model = combo.get_model() ftid = model[combo_iter][0] self.watched_stop = model[combo_iter][1] self.bus_lines = self.gmm.get_stop_metadata(ftid) if self.bus_lines: self.stop_assoc_lines.clear() for subscript, line in enumerate(self.bus_lines["lines"]): self.stop_assoc_lines.append([subscript, " - ".join([line["line"], line.get("direction", "")])]) pass def on_select_line(self, combo): combo_iter = combo.get_active_iter() if combo_iter != None: model = combo.get_model() line_index = model[combo_iter][0] if self.bus_lines and line_index < len(self.bus_lines["lines"]): self.watch(self.bus_lines["lines"][line_index]) def watch(self, line): self.watched_line = " - ".join([line["line"], line.get("direction", "")]) self.watched_schedules = [ datetime.combine(datetime.today(), datetime.strptime(tp[0], "%I:%M %p").time()) for tp in line["schedules"] ] self.title_label.set_label("Start watching " + self.watched_line) self.combo_lines.set_sensitive(False) self.combo_bus_stops.set_sensitive(False) self.check_schedule(immediate=True) def check_schedule(self, immediate=False): for t in self.watched_schedules: minutes_to_due = floor((t - datetime.now()).total_seconds() / 60.0) if immediate and minutes_to_due > 0 or (minutes_to_due <= 20 and minutes_to_due in (0, 5, 10, 20)): notify = Notify.Notification.new( "%s is due in %d minutes" % (self.watched_line, minutes_to_due), "@ %s on %s" % (self.watched_stop, t.strftime("%I:%M %p")), None, ) notify.show() break # set next timeout GObject.timeout_add_seconds(60, self.check_schedule) def proximity_search(self, lat, lng, radius=500, zoom=17): mx, my = self.mercator.LatLonToMeters(lat, lng) tx_prime, ty_prime = self.mercator.MetersToTile(mx - radius, my + radius, zoom) tx_prime, ty_prime = self.mercator.GoogleTile(tx_prime, ty_prime, zoom) tx, ty = self.mercator.MetersToTile(mx, my, zoom) tx, ty = self.mercator.GoogleTile(tx, ty, zoom) landmarks = self.gmm.get_landmarks(tx_prime, ty_prime, max(tx - tx_prime, ty - ty_prime) * 2) stops = self.gmm.extract_bus_stops(landmarks) return stops