1 #!/usr/bin/env python2.5
2 # -*- coding: utf-8 -*-
3 """ Main-view UI for fMMS
5 @author: Nick Leppänen Larsson <frals@frals.se>
16 from gnome import gnomevfs
18 from wappushhandler import PushHandler
19 import fmms_config as fMMSconf
20 import fmms_sender_ui as fMMSSenderUI
21 import fmms_viewer as fMMSViewer
22 import controller as fMMSController
23 import contacts as ContactH
25 class fMMS_GUI(hildon.Program):
28 self.cont = fMMSController.fMMS_controller()
29 self.config = fMMSconf.fMMS_config()
30 self._mmsdir = self.config.get_mmsdir()
31 self._pushdir = self.config.get_pushdir()
32 self.ch = ContactH.ContactHandler()
33 self.osso_c = osso.Context("fMMS", "0.1.0", False)
35 if not os.path.isdir(self._mmsdir):
36 print "creating dir", self._mmsdir
37 os.makedirs(self._mmsdir)
38 if not os.path.isdir(self._pushdir):
39 print "creating dir", self._pushdir
40 os.makedirs(self._pushdir)
42 hildon.Program.__init__(self)
43 program = hildon.Program.get_instance()
45 self.osso_rpc = osso.Rpc(self.osso_c)
46 self.osso_rpc.set_rpc_callback("se.frals.fmms","/se/frals/fmms","se.frals.fmms", self.cb_open_fmms, self.osso_c)
48 self.window = hildon.StackableWindow()
49 self.window.set_title("fMMS")
50 program.add_window(self.window)
52 self.window.connect("delete_event", self.quit)
54 pan = hildon.PannableArea()
55 pan.set_property("mov-mode", hildon.MOVEMENT_MODE_BOTH)
58 ### TODO: dont hardcode the values here.. oh well
59 iconcell = gtk.CellRendererPixbuf()
60 photocell = gtk.CellRendererPixbuf()
61 textcell = gtk.CellRendererText()
62 iconcell.set_fixed_size(48, 64)
63 cell2 = gtk.CellRendererText()
64 cell2.set_property('xalign', 1.0)
65 photocell.set_property('xalign', 1.0)
66 photocell.set_fixed_size(64, 64)
67 textcell.set_property('mode', gtk.CELL_RENDERER_MODE_INERT)
68 textcell.set_fixed_size(650, 64)
69 textcell.set_property('xalign', 0.0)
71 self.liststore = gtk.ListStore(gtk.gdk.Pixbuf, str, gtk.gdk.Pixbuf, str)
72 self.treeview = hildon.GtkTreeView(gtk.HILDON_UI_MODE_EDIT)
73 self.treeview.set_model(self.liststore)
76 icon_col = gtk.TreeViewColumn('Icon')
77 sender_col = gtk.TreeViewColumn('Sender')
78 placeholder_col = gtk.TreeViewColumn('Photo')
81 self.add_buttons_liststore()
83 self.treeview.append_column(icon_col)
84 self.treeview.append_column(sender_col)
85 self.treeview.append_column(placeholder_col)
87 icon_col.pack_start(iconcell, False)
88 icon_col.set_attributes(iconcell, pixbuf=0)
89 sender_col.pack_start(textcell, True)
90 sender_col.set_attributes(textcell, markup=1)
91 placeholder_col.pack_end(photocell, False)
92 placeholder_col.set_attributes(photocell, pixbuf=2)
94 selection = self.treeview.get_selection()
95 #selection.set_mode(gtk.SELECTION_SINGLE)
96 self.treeview.connect('hildon-row-tapped', self.show_mms)
99 self.liststore_menu = self.liststore_mms_menu()
100 self.treeview.tap_and_hold_setup(self.liststore_menu)
101 #treeview.connect('tap-and-hold', self.liststore_mms_clicked)
104 pan.add_with_viewport(self.treeview)
107 self.menu = self.create_menu()
108 self.window.set_app_menu(self.menu)
109 self.window.show_all()
110 self.add_window(self.window)
112 if self.config.get_firstlaunch() == 1:
114 note = osso.SystemNote(self.osso_c)
115 firstlaunchmessage = "NOTE: Currently you have to connect manually to the MMS APN when sending and receiving.\nAlso, only implemented attachment is image."
116 note.system_note_dialog(firstlaunchmessage , 'notice')
117 self.create_config_dialog()
118 self.config.set_firstlaunch(0)
120 def cb_open_fmms(self, interface, method, args, user_data):
121 if method != 'open_mms' and method != 'open_gui':
123 if method == 'open_mms':
125 checkfile = os.path.isfile(self._pushdir + args[0])
126 if checkfile == True:
130 viewer = fMMSViewer.fMMS_Viewer(filename)
131 elif method == 'open_gui':
132 print "open_gui called"
133 self.liststore.clear()
134 self.add_buttons_liststore()
137 def create_menu(self):
138 menu = hildon.AppMenu()
140 send = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
141 send.set_label("New MMS")
142 send.connect('clicked', self.menu_button_clicked)
144 config = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
145 config.set_label("Configuration")
146 config.connect('clicked', self.menu_button_clicked)
148 about = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
149 about.set_label("About")
150 about.connect('clicked', self.menu_button_clicked)
160 def menu_button_clicked(self, button):
161 buttontext = button.get_label()
162 if buttontext == "Configuration":
163 ret = self.create_config_dialog()
164 elif buttontext == "New MMS":
165 ret = fMMSSenderUI.fMMS_GUI(self.window).run()
166 elif buttontext == "About":
167 ret = self.create_about_dialog()
169 def create_about_dialog(self):
170 dialog = gtk.AboutDialog()
171 dialog.set_name("fMMS")
172 fmms_logo = gtk.gdk.pixbuf_new_from_file("/opt/fmms/fmms.png")
173 dialog.set_logo(fmms_logo)
174 dialog.set_comments('MMS send and receive support for Fremantle')
175 dialog.set_version(self.config.get_version())
176 dialog.set_copyright("By Nick Leppänen Larsson (aka frals)")
177 dialog.set_website("http://mms.frals.se/")
178 dialog.connect("response", lambda d, r: d.destroy())
181 def create_config_dialog(self):
182 dialog = gtk.Dialog()
183 dialog.set_title("Configuration")
187 self.active_apn_index = 0
190 apn_label = gtk.Label("APN:")
191 self.selector = self.create_apn_selector()
192 self.apn = hildon.PickerButton(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
193 self.apn.set_selector(self.selector)
194 self.apn.set_active(self.active_apn_index)
196 apnHBox.pack_start(apn_label, False, True, 0)
197 apnHBox.pack_start(self.apn, True, True, 0)
199 mmscHBox = gtk.HBox()
200 mmsc_label = gtk.Label("MMSC:")
201 self.mmsc = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
202 mmsc_text = self.config.get_mmsc()
203 if mmsc_text != None:
204 self.mmsc.set_text(mmsc_text)
206 self.mmsc.set_text("http://")
207 mmscHBox.pack_start(mmsc_label, False, True, 0)
208 mmscHBox.pack_start(self.mmsc, True, True, 0)
210 numberHBox = gtk.HBox()
211 number_label = gtk.Label("Your phonenumber:")
212 self.number = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
213 number_text = self.config.get_phonenumber()
214 if number_text != None:
215 self.number.set_text(number_text)
217 self.number.set_text("")
218 numberHBox.pack_start(number_label, False, True, 0)
219 numberHBox.pack_start(self.number, True, True, 0)
221 imgwidthHBox = gtk.HBox()
222 imgwidth_label = gtk.Label("Resize image width:")
223 self.imgwidth = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
224 imgwidth_text = self.config.get_img_resize_width()
225 if imgwidth_text != None:
226 self.imgwidth.set_text(str(imgwidth_text))
228 self.imgwidth.set_text("")
229 imgwidthHBox.pack_start(imgwidth_label, False, True, 0)
230 imgwidthHBox.pack_start(self.imgwidth, True, True, 0)
232 notelabel = gtk.Label("APN refers to the name of the connection in\n \"Internet Connections\" to use.")
234 allVBox.pack_start(notelabel, False, True, 0)
235 allVBox.pack_start(apnHBox, False, False, 0)
236 allVBox.pack_start(mmscHBox, False, False, 0)
237 allVBox.pack_end(numberHBox, False, False, 0)
238 allVBox.pack_end(imgwidthHBox, False, False, 0)
241 dialog.vbox.add(allVBox)
242 dialog.add_button("Save", gtk.RESPONSE_APPLY)
245 ret2 = self.config_menu_button_clicked(ret)
246 if ret2 == 0 or ret2 == None:
253 """ selector for apn """
254 def create_apn_selector(self):
255 selector = hildon.TouchSelector(text = True)
256 apnlist = self.config.get_gprs_apns()
257 currval = self.config.get_apn_nicename()
263 self.active_apn_index = i
265 # Add item to the column
266 selector.append_text(apn)
268 selector.center_on_selected()
269 selector.set_active(0, i)
270 # Set selection mode to allow multiple selection
271 selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
275 def config_menu_button_clicked(self, action):
276 if action == gtk.RESPONSE_APPLY:
277 print self.apn.get_selector().get_current_text()
278 ret_setapn = self.config.get_apnid_from_name(self.apn.get_selector().get_current_text())
279 if ret_setapn != None:
280 self.config.set_apn(ret_setapn)
281 print "Set apn to: %s" % ret_setapn
282 ret = self.config.set_mmsc(self.mmsc.get_text())
283 print "Set mmsc to %s" % self.mmsc.get_text()
284 self.config.set_phonenumber(self.number.get_text())
285 print "Set phonenumber to %s" % self.number.get_text()
286 self.config.set_img_resize_width(self.imgwidth.get_text())
287 print "Set image width to %s" % self.imgwidth.get_text()
288 banner = hildon.hildon_banner_show_information(self.window, "", "Settings saved")
291 print "Set mmsc to %s" % self.mmsc.get_text()
292 self.config.set_phonenumber(self.number.get_text())
293 print "Set phonenumber to %s" % self.number.get_text()
294 self.config.set_img_resize_width(self.imgwidth.get_text())
295 print "Set image width to %s" % self.imgwidth.get_text()
296 banner = hildon.hildon_banner_show_information(self.window, "", "Could not save APN settings. Did you enter a correct APN?")
297 banner.set_timeout(5000)
301 """ add each item to our liststore """
302 def add_buttons_liststore(self):
303 icon_theme = gtk.icon_theme_get_default()
305 pushlist = self.cont.get_push_list()
306 for varlist in pushlist:
307 mtime = varlist['Time']
308 fname = varlist['Transaction-Id']
309 direction = self.cont.get_direction_mms(fname)
311 sender = varlist['From']
312 sender = sender.replace("/TYPE=PLMN", "")
316 if direction == fMMSController.MSG_DIRECTION_OUT:
317 sender = "You (Outgoing)"
319 sendername = self.ch.get_name_from_number(sender)
320 photo = icon_theme.load_icon("general_default_avatar", 48, 0)
321 if sendername != None:
322 sender = sendername + ' <span size="smaller">(' + sender + ')</span>'
323 phototest = self.ch.get_photo_from_name(sendername, 64)
324 if phototest != None:
326 #print "loaded photo:", photo.get_width(), photo.get_height()
328 #title = sender + " - " + mtime
330 if self.cont.is_fetched_push_by_transid(fname):
331 icon = icon_theme.load_icon("general_sms", 48, 0)
333 icon = icon_theme.load_icon("chat_unread_sms", 48, 0)
334 self.liststore.append([icon, sender + ' <span foreground="#666666" size="smaller"><sup>' + mtime + '</sup></span>\n<span foreground="#666666" size="x-small">' + fname + '</span>', photo, fname])
336 """ lets call it quits! """
337 def quit(self, *args):
341 """ forces ui update, kinda... god this is AWESOME """
342 def force_ui_update(self):
343 while gtk.events_pending():
344 gtk.main_iteration(False)
347 """ delete push message """
348 def delete_push(self, fname):
349 self.cont.delete_push_message(fname)
352 """ delete mms message (eg for redownload) """
353 def delete_mms(self, fname):
354 self.cont.delete_mms_message(fname)
356 """ delete push & mms """
357 def delete_push_mms(self, fname):
359 self.cont.wipe_message(fname)
360 banner = hildon.hildon_banner_show_information(self.window, "", "fMMS: Message deleted")
362 print "Exception caught:"
365 banner = hildon.hildon_banner_show_information(self.window, "", "fMMS: Failed to delete message.")
368 """ action on delete contextmenu click """
369 def liststore_delete_clicked(self, widget):
370 dialog = gtk.Dialog()
371 dialog.set_title("Confirm")
372 dialog.add_button(gtk.STOCK_YES, 1)
373 dialog.add_button(gtk.STOCK_NO, 0)
374 label = gtk.Label("Are you sure you want to delete the message?")
375 dialog.vbox.add(label)
379 (model, miter) = self.treeview.get_selection().get_selected()
380 # the 4th value is the filename (start counting at 0)
381 filename = model.get_value(miter, 3)
382 print "deleting", filename
383 self.delete_push_mms(filename)
384 self.liststore.remove(miter)
388 """ action on redl contextmenu click """
389 def liststore_redl_clicked(self, widget):
390 hildon.hildon_gtk_window_set_progress_indicator(self.window, 1)
391 dialog = gtk.Dialog()
392 dialog.set_title("WARNING")
393 dialog.add_button(gtk.STOCK_YES, 1)
394 dialog.add_button(gtk.STOCK_NO, 0)
395 label = gtk.Label("If the message is no longer on your MMSC,\n the message will be lost. Continue?")
396 dialog.vbox.add(label)
400 self.force_ui_update()
403 (model, miter) = self.treeview.get_selection().get_selected()
404 # the 4th value is the filename (start counting at 0)
405 filename = model.get_value(miter, 3)
406 print "redownloading", filename
408 self.delete_mms(filename)
409 banner = hildon.hildon_banner_show_information(self.window, "", "fMMS: Trying to download MMS...")
410 self.force_ui_update()
414 self.cont.get_mms_from_push(filename)
415 self.show_mms(self.treeview, model.get_path(miter))
419 banner = hildon.hildon_banner_show_information(self.window, "", "fMMS: Operation failed")
420 hildon.hildon_gtk_window_set_progress_indicator(self.window, 0)
423 """ long press on image creates this """
424 def liststore_mms_menu(self):
426 menu.set_title("hildon-context-sensitive-menu")
428 redlItem = gtk.MenuItem("Redownload")
429 menu.append(redlItem)
430 redlItem.connect("activate", self.liststore_redl_clicked)
433 separator = gtk.MenuItem()
434 menu.append(separator)
437 openItem = gtk.MenuItem("Delete")
438 menu.append(openItem)
439 openItem.connect("activate", self.liststore_delete_clicked)
445 """ show the selected mms """
446 def show_mms(self, treeview, path):
447 # Show loading indicator
448 hildon.hildon_gtk_window_set_progress_indicator(self.window, 1)
449 banner = hildon.hildon_banner_show_information(self.window, "", "fMMS: Opening message")
450 self.force_ui_update()
453 model = treeview.get_model()
454 miter = model.get_iter(path)
455 # the 4th value is the transactionid (start counting at 0)
456 transactionid = model.get_value(miter, 3)
459 viewer = fMMSViewer.fMMS_Viewer(transactionid)
465 hildon.hildon_gtk_window_set_progress_indicator(self.window, 0)
468 self.window.show_all()
471 if __name__ == "__main__":