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