d360de9b6b852060b4786028523df7251b604d00
[gigfinder] / src / opt / gigfinder / gigfinder.py
1 #!/usr/bin/env python
2
3 """Simple program to display local gigs
4
5 Intended for use on the N900, uses the devices gps to find local gigs.
6 """
7
8 __authors__ = ["Jon Staley"]
9 __copyright__ = "Copyright 2010 Jon Staley"
10 __license__ = "MIT"
11 __version__ = "0.0.1"
12
13 import gtk
14 import hildon
15 import time
16 import gobject
17 import os.path
18 from threading import Thread
19 import thread
20
21 from locator import LocationUpdater
22 from events import Events
23
24 gtk.gdk.threads_init()
25
26 # TODO: 
27 # Add user settings for distance, date
28 # maybe switch to json
29 # maybe do km to mile conversions
30
31 class GigFinder:
32
33     def __init__(self):
34         self.lat = None
35         self.long = None
36         self.distance = '10'
37         self.banner = None
38         self.location = LocationUpdater()
39         self.events = Events()
40         self.win = hildon.StackableWindow()
41         self.app_title = "Gig Finder"
42
43     def main(self):
44         """ Build the gui and start the update thread """
45         program = hildon.Program.get_instance()
46         menu = self.create_menu()
47
48         self.win.set_title(self.app_title)
49         self.win.connect("destroy", gtk.main_quit, None)
50         self.win.set_app_menu(menu)
51         self.add_button_area()
52
53         Thread(target=self.update_gigs).start()
54
55         self.win.show_all()
56         gtk.main()
57
58     def show_about(self, widget, data):
59         """ Show about dialog """
60         dialog = gtk.AboutDialog()
61         dialog.set_name('Gig Finder')
62         dialog.set_version(__version__)
63         dialog.set_authors(__authors__)
64         dialog.set_comments('Display gigs close by.\nUsing the http://www.last.fm api.')
65         dialog.set_license('Distributed under the MIT license.\nhttp://www.opensource.org/licenses/mit-license.php')
66         dialog.set_copyright(__copyright__)
67         dialog.show_all()
68
69     def update(self, widget, data):
70         """ Start update process """
71         self.win.set_title(self.app_title)
72         self.location.reset()
73         self.win.remove(self.pannable_area)
74         Thread(target=self.update_gigs).start()
75
76     def update_gigs(self):
77         """ Get gig info """
78         gobject.idle_add(self.show_message, "Getting events")
79         
80         if not 'applications' in os.path.abspath(__file__):
81             gobject.idle_add(self.location.update_location)
82
83             # if no gps fix wait
84             # TODO: needs a timeout
85             while not self.location.lat or not self.location.long:
86                 time.sleep(1)
87         else:
88             self.location.lat = float(51.517369)
89             self.location.long = float(-0.082998)
90          
91         events = self.events.get_events(self.location.lat, 
92                                         self.location.long, 
93                                         self.distance,)
94         gobject.idle_add(self.show_events, events)
95         gobject.idle_add(self.hide_message)
96         thread.exit()
97
98     def show_message(self, message):
99         """ Set window progress indicator and show message """
100         hildon.hildon_gtk_window_set_progress_indicator(self.win, 1)
101         self.banner = hildon.hildon_banner_show_information(self.win,
102                                                             '', 
103                                                             message)
104
105     def hide_message(self):
106         """ Hide banner and set progress indicator """
107         self.banner.hide()
108         hildon.hildon_gtk_window_set_progress_indicator(self.win, 0)
109
110     def show_events(self, events):
111         """ Sort events, set new window title and add events to table """
112         if events:
113             self.win.set_title('%s (%s)' % (self.app_title, len(events)))
114             self.add_events(events)
115         else:
116             label = gtk.Label('No events available')
117             vbox = gtk.VBox(False, 0)
118             vbox.pack_start(label, True, True, 0)
119             vbox.show_all()
120             self.win.add(vbox)
121
122     def create_menu(self):
123         """ Build application menu """
124         update_button = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
125         update_button.set_label('Update')
126         update_button.connect('clicked',
127                               self.update,
128                               None)
129
130         about_button = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
131         about_button.set_label('About')
132         about_button.connect('clicked',
133                              self.show_about,
134                              None)
135
136         menu = hildon.AppMenu()
137         menu.append(update_button)
138         menu.append(about_button)
139         menu.show_all()
140         return menu
141
142     def show_details(self, widget, data):
143         """ Open new window showing gig details """
144         win = hildon.StackableWindow()
145         win.set_title(data.title)
146
147         win.vbox = gtk.VBox()
148         win.add(win.vbox)
149
150         scroll = hildon.PannableArea()
151         win.vbox.pack_start(scroll, True, True, 0)
152
153         view = hildon.TextView()
154         view.set_editable(False)
155         view.unset_flags(gtk.CAN_FOCUS)
156         view.set_wrap_mode(gtk.WRAP_WORD)
157         buffer = view.get_buffer()
158         end = buffer.get_end_iter()
159         buffer.insert(end, '%s\n' % data.title)
160         buffer.insert(end, 'Artists: %s\n' % data.artists)
161         buffer.insert(end, 'Venue: %s\n' % data.venue_name)
162         buffer.insert(end, '%s\n' % data.address)
163         buffer.insert(end, 'When: %s\n' % data.start_date.strftime('%H:%M %d/%m/%Y'))
164         buffer.insert(end, '\n')
165         scroll.add_with_viewport(view)
166
167         win.show_all()
168
169     def add_button_area(self):
170         self.box = gtk.VBox(True,0)
171         self.pannable_area = hildon.PannableArea()
172         self.pannable_area.add_with_viewport(self.box)
173         self.pannable_area.show_all()
174         self.win.add(self.pannable_area)
175         
176     def add_events(self, events):
177         """ Add a table of buttons """
178         for event in events:
179             button = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, 
180                                    hildon.BUTTON_ARRANGEMENT_VERTICAL)
181             button.set_text(event.title, "distance: %0.02f km" % event.get_distance_from(self.location.long, self.location.lat))
182             button.connect("clicked", self.show_details, event)
183             self.box.pack_start(button)
184         self.box.show_all()
185             
186 if __name__ == "__main__":
187     finder = GigFinder()
188     finder.main()