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