c06d36f22801dc7bf533ff06779281113b46d1a1
[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         gtk.gdk.threads_enter()
46         program = hildon.Program.get_instance()
47         menu = self.create_menu()
48
49         self.win.set_title(self.app_title)
50         self.win.connect("destroy", self.quit, None)
51         self.win.set_app_menu(menu)
52
53         self.update(None, None)
54
55         self.win.show_all()
56         gtk.main()
57         gtk.gdk.threads_leave()
58
59     def quit(self, widget, data):
60         self.location.stop(widget, data)
61         thread.exit()
62         gtk.main_quit()
63         return False
64
65     def show_about(self, widget, data):
66         """ Show about dialog """
67         dialog = gtk.AboutDialog()
68         dialog.set_name('Gig Finder')
69         dialog.set_version(__version__)
70         dialog.set_authors(__authors__)
71         dialog.set_comments('Display gigs close by.\nUsing the http://www.last.fm api.')
72         dialog.set_license('Distributed under the MIT license.\nhttp://www.opensource.org/licenses/mit-license.php')
73         dialog.set_copyright(__copyright__)
74         dialog.show_all()
75
76     def show_message(self, message):
77         """ Set window progress indicator and show message """
78         hildon.hildon_gtk_window_set_progress_indicator(self.win, 1)
79         self.banner = hildon.hildon_banner_show_information(self.win,
80                                                             '', 
81                                                             message)
82
83     def hide_message(self):
84         """ Hide banner and set progress indicator """
85         self.banner.hide()
86         hildon.hildon_gtk_window_set_progress_indicator(self.win, 0)
87
88     def show_events(self, events):
89         """ Sort events, set new window title and add events to table """
90         if events:
91             self.win.set_title('%s (%s)' % (self.app_title, len(events)))
92             self.add_events(events)
93         else:
94             label = gtk.Label('No events available')
95             vbox = gtk.VBox(False, 0)
96             vbox.pack_start(label, True, True, 0)
97             vbox.show_all()
98             self.win.add(vbox)
99
100     def create_menu(self):
101         """ Build application menu """
102         update_button = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
103         update_button.set_label('Update')
104         update_button.connect('clicked',
105                               self.update,
106                               None)
107
108         about_button = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
109         about_button.set_label('About')
110         about_button.connect('clicked',
111                              self.show_about,
112                              None)
113
114         menu = hildon.AppMenu()
115         menu.append(update_button)
116         menu.append(about_button)
117         menu.show_all()
118         return menu
119
120     def show_details(self, widget, data):
121         """ Open new window showing gig details """
122         win = hildon.StackableWindow()
123         win.set_title(data.title)
124
125         win.vbox = gtk.VBox()
126         win.add(win.vbox)
127
128         scroll = hildon.PannableArea()
129         win.vbox.pack_start(scroll, True, True, 0)
130
131         view = hildon.TextView()
132         view.set_editable(False)
133         view.unset_flags(gtk.CAN_FOCUS)
134         view.set_wrap_mode(gtk.WRAP_WORD)
135         buffer = view.get_buffer()
136         end = buffer.get_end_iter()
137         buffer.insert(end, '%s\n' % data.title)
138         buffer.insert(end, 'Artists: %s\n' % data.artists)
139         buffer.insert(end, 'Venue: %s\n' % data.venue_name)
140         buffer.insert(end, '%s\n' % data.address)
141         buffer.insert(end, 'When: %s\n' % data.start_date.strftime('%H:%M %d/%m/%Y'))
142         buffer.insert(end, '\n')
143         scroll.add_with_viewport(view)
144
145         win.show_all()
146
147     def add_button_area(self):
148         self.box = gtk.VBox(True,0)
149         self.pannable_area = hildon.PannableArea()
150         self.pannable_area.add_with_viewport(self.box)
151         self.pannable_area.show_all()
152         self.win.add(self.pannable_area)
153         
154     def add_events(self, events):
155         """ Add a table of buttons """
156         for event in events:
157             button = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, 
158                                    hildon.BUTTON_ARRANGEMENT_VERTICAL)
159             button.set_text(event.title, "distance: %0.02f km" % event.get_distance_from(self.location.long, self.location.lat))
160             button.connect("clicked", self.show_details, event)
161             self.box.pack_start(button)
162         self.box.show_all()
163             
164     def update(self, widget, data):
165         """ Start update process """
166         self.win.set_title(self.app_title)
167         self.location.reset()
168         if getattr(self, 'pannable_area', None):
169             self.win.remove(self.pannable_area)
170         self.add_button_area()
171         self.location.update_location()
172         Thread(target=self.update_gigs).start()
173
174     def update_gigs(self):
175         """ Get gig info """
176         gobject.idle_add(self.show_message, "Getting events")
177         
178         if not 'applications' in os.path.abspath(__file__):
179             # if no gps fix wait
180             while not self.location.lat or not self.location.long:
181                 time.sleep(1)
182         else:
183             self.location.lat = float(51.517369)
184             self.location.long = float(-0.082998)
185          
186         events = self.events.get_events(self.location.lat, 
187                                         self.location.long, 
188                                         self.distance,)
189         gobject.idle_add(self.show_events, events)
190         gobject.idle_add(self.hide_message)
191         return True
192
193 if __name__ == "__main__":
194     finder = GigFinder()
195     finder.main()