def _build_sms_menu(self, pathlist, treeview): selected = self._get_selected_objects(treeview) menu = gtk.Menu() if len(selected["objs"]) == 1: # only show reply or send from storage when only one SMS is sel obj = selected["objs"][0] item = None if obj.where <= STO_INBOX: item = gtk.MenuItem(_("_Reply")) callback = self._send_sms_to_contact elif obj.where == STO_DRAFTS: item = gtk.MenuItem(_("_Send")) callback = self._send_sms_from_storage elif obj.where == STO_SENT: # if the SMS is in STO_SENT then only deleting is allowed pass if item: item.connect("activate", callback, treeview) item.show() menu.append(item) item = gtk.ImageMenuItem(_("_Delete")) img = gtk.image_new_from_stock(gtk.STOCK_DELETE, gtk.ICON_SIZE_MENU) item.set_image(img) item.connect("activate", self._delete_rows, pathlist, treeview) item.show() menu.append(item) return menu
def ask_puk2_dialog(parent): logger.debug("Asking for PUK2") return generic_puk_dialog( _("PUK2 required"), _("Please, insert the PUK2 and PIN of your SIM card"), parent, puk_regexp=re.compile('^\d{8}$'), pin_regexp=re.compile('^\d{4,8}$'))
def get_trayicon_menu(self): menu = gtk.Menu() item = gtk.ImageMenuItem(_("About")) img = gtk.image_new_from_stock(gtk.STOCK_ABOUT, gtk.ICON_SIZE_MENU) item.set_image(img) item.connect("activate", self.on_about_menuitem_activate) item.show() menu.append(item) item = gtk.ImageMenuItem(_("Preferences")) item.set_image(gtk.image_new_from_stock(gtk.STOCK_PREFERENCES, gtk.ICON_SIZE_MENU)) item.connect("activate", self.on_preferences_menu_item_activate) if self.model.device is None: item.set_sensitive(False) else: item.set_sensitive(True) item.show() menu.append(item) item = gtk.ImageMenuItem(_("Quit")) img = gtk.image_new_from_stock(gtk.STOCK_QUIT, gtk.ICON_SIZE_MENU) item.set_image(img) item.connect("activate", self.close_application) item.show() menu.append(item) return menu
def on_keyring_password_required(self, opath, callback=None): from wader.gtk.profiles import manager profile = manager.get_profile_by_object_path(opath) password = None if profile.secrets.manager.is_new(): dialog = NewKeyringDialog(self.view.get_top_widget()) response = dialog.run() elif not profile.secrets.manager.is_open(): dialog = KeyringPasswordDialog(self.view.get_top_widget()) response = dialog.run() if response == gtk.RESPONSE_OK: password = dialog.password_entry.get_text() dialog.destroy() if password is not None: try: profile.secrets.manager.open(password) except KeyringInvalidPassword: title = _("Invalid password") details = _("The supplied password is incorrect") show_error_dialog(title, details) # call ourselves again self.on_keyring_password_required(opath) else: if callback is not None: uuid = profile.get_settings()['connection']['uuid'] callback(profile.secrets.manager.get_secrets(uuid))
def on_save_toolbutton_clicked(self, widget): numbers = self.view.get_numbers() text = self.view.get_text() if not numbers: title = _("Invalid number") msg = _("You must provide a valid number") dialogs.show_error_dialog(title, msg) self.view["contacts_entry"].grab_focus() return if text == "": title = _("No text to save") msg = _("Are you sure you want to store a blank message?") if not dialogs.show_warning_request_cancel_ok(title, msg): # user cancelled it self.view["text_textview"].grab_focus() return self.messages = [Message(num, text) for num in numbers] for sms in self.messages: self.model.device.Save( sms.to_dict(), dbus_interface=SMS_INTFACE, reply_handler=self.on_sms_saved_cb, error_handler=self.on_sms_saved_eb, )
def setup_view(self, view): self.view['profile_name_entry'].set_text(self.model.name) self.view['username_entry'].set_text(self.model.username) self.view.set_network_mode(self.model.network_type) self.view.set_band(self.model.band) self.view['apn_entry'].set_text(self.model.apn) self.view['static_dns_check'].set_active(self.model.static_dns) if self.model.primary_dns: dns1 = convert_int_to_ip(self.model.primary_dns) self.view['primary_dns_entry'].set_text(dns1) if self.model.secondary_dns: dns2 = convert_int_to_ip(self.model.secondary_dns) self.view['secondary_dns_entry'].set_text(dns2) if self.model.static_dns: self.view.enable_static_dns() if not self.model.password: try: self.model.load_password() except KeyringNoMatchError, e: logger.error("Error while loading connection password: %s" % e) title = _("Error while getting connection password") details = _("NoMatchError: No password was retrieved " "from connection, please set one again") show_error_dialog(title, details) return
def property_status_value_change(self, model, old, new): self.view.set_status(new) if new == _('Initialising'): self.view.set_initialising(True) elif new == _('No device'): self.view.set_disconnected(device_present=False) elif new in [_('Registered'), _('Roaming')]: self.view.set_initialising(False)
def _init_wader_object(self): try: self.obj = self.bus.get_object(WADER_SERVICE, WADER_OBJPATH) except dbus.DBusException, e: title = _("Error while starting wader") details = _("Check that your installation is correct and your " " OS/distro is supported: %s" % e) show_error_dialog(title, details) raise SystemExit()
def find_by_number_cb(contacts): if not contacts: title = _("SMS received from %s") % sms['number'] else: assert len(contacts) == 1, "More than one match for a number!" title = _("SMS received from %s") % contacts[0][1] n = new_notification(self.icon, title, sms['text'], stock=gtk.STOCK_INFO) n.show()
def close_application(self, *args): if self.model.dial_path: show_warning_dialog(_("Can not close application"), _("Can not close while a connection is active")) window = self.view.get_top_widget() try: window.emit_stop_by_name('delete_event') except IOError: pass return True else: self.view.start_throbber() self.model.quit(self._close_application_cb)
def _device_removed_cb(self, opath): logger.info('Device with opath %s removed' % opath) if self.device_opath: logger.info('Device path: %s' % self.device_opath) if opath == self.device_opath: self.device = None self.device_opath = None self.dial_path = None self.operator = _('Unknown') self.status = _('No device') self.tech = '----' self.rssi = 0
def _build_contact_menu(self, pathlist, treeview): menu = gtk.Menu() item = gtk.MenuItem(_("_Send SMS")) item.connect("activate", self._send_sms_to_contact, treeview) item.show() menu.append(item) item = gtk.ImageMenuItem(_("_Delete")) img = gtk.image_new_from_stock(gtk.STOCK_DELETE, gtk.ICON_SIZE_MENU) item.set_image(img) item.connect("activate", self._delete_rows, pathlist, treeview) item.show() menu.append(item) return menu
def get_categories_model(self): if self.categories is None: model = CategoriesModel() # SMS # inbox inbox_path = os.path.join(GLADE_DIR, 'inbox.png') inbox_pixbuf = gtk.gdk.pixbuf_new_from_file(inbox_path) def inbox_visible_func(m, _iter): obj = m.get_value(_iter, m.COL_OBJECT) return (False if not obj else obj.where == STO_INBOX) model.add_category(Category(_("Inbox"), parent=model.sms_iter, pixbuf=inbox_pixbuf, visible_func=inbox_visible_func)) # drafts drafts_path = os.path.join(GLADE_DIR, 'folder.png') drafts_pixbuf = gtk.gdk.pixbuf_new_from_file(drafts_path) def drafts_visible_func(m, _iter): obj = m.get_value(_iter, m.COL_OBJECT) return (False if not obj else obj.where == STO_DRAFTS) model.add_category(Category(_("Drafts"), parent=model.sms_iter, pixbuf=drafts_pixbuf, visible_func=drafts_visible_func)) # sent sent_path = os.path.join(GLADE_DIR, 'mail-sent.png') sent_pixbuf = gtk.gdk.pixbuf_new_from_file(sent_path) def sent_visible_func(m, _iter): obj = m.get_value(_iter, m.COL_OBJECT) return (False if not obj else obj.where == STO_SENT) model.add_category(Category(_("Sent"), parent=model.sms_iter, pixbuf=sent_pixbuf, visible_func=sent_visible_func)) # Contacts cts_path = os.path.join(GLADE_DIR, 'contacts.png') cts_pixbuf = gtk.gdk.pixbuf_new_from_file(cts_path) model.add_category(Category(_("SIM"), parent=model.cts_iter, pixbuf=cts_pixbuf)) self.categories = model return self.categories
def on_ok_button_clicked(self, widget): self.model.name = self.view['profile_name_entry'].get_text() self.model.username = self.view['username_entry'].get_text() self.model.password = self.view['password_entry'].get_text() mode = self.view['connection_combobox'].get_active_text() band = self.view['band_combobox'].get_active_text() if mode: self.model.network_type = MODE_MAP_REV[mode] if band: self.model.band = BAND_MAP_REV[band] self.model.apn = self.view['apn_entry'].get_text() self.model.static_dns = self.view['static_dns_check'].get_active() if self.view['static_dns_check'].get_active(): dns1 = self.view['primary_dns_entry'].get_text() dns2 = self.view['secondary_dns_entry'].get_text() if dns1: self.model.primary_dns = convert_ip_to_int(dns1) if dns2: self.model.secondary_dns = convert_ip_to_int(dns2) try: self.model.save() except RuntimeError, e: show_error_dialog(_("Error creating profile"), get_error_msg(e))
def on_preferences_menu_item_activate(self, widget): from wader.gtk.views.preferences import PreferencesView from wader.gtk.controllers.preferences import PreferencesController view = PreferencesView() controller = PreferencesController(self.model.preferences_model, view, lambda: self.model.device) profiles_model = self.model.preferences_model.profiles_model if not profiles_model.has_active_profile(): show_warning_dialog( _("Profile needed"), _("You need to create a profile to save preferences")) self.ask_for_new_profile() return view.show()
def _get_regstatus(self, first_time=False): self.device.GetRegistrationInfo(dbus_interface=NET_INTFACE, reply_handler=self._get_regstatus_cb, error_handler=lambda e: logger.warn("Error getting registration " "status: %s " % get_error_msg(e))) if not first_time and self.status != _("Scanning"): return False
def on_delete_profile_button_clicked(self, event): _iter = self.view.profiles_treeview.get_selection().get_selected()[1] profile = self.model.profiles_model.get_value(_iter, 1) if profile: try: self.model.profiles_model.remove_profile(profile) except ProfileNotFoundError, e: show_error_dialog(_("Error while removing profile"), get_error_msg(e))
def setup_treeview(self, model): treeview = self["contact_treeview"] treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE) cell = gtk.CellRendererText() column = gtk.TreeViewColumn(_("Name"), cell, text=model.COL_NAME) column.set_resizable(True) column.set_sort_column_id(model.COL_NAME) cell.set_property("editable", False) treeview.append_column(column) cell = gtk.CellRendererText() column = gtk.TreeViewColumn(_("Number"), cell, text=model.COL_NUMBER) column.set_resizable(True) column.set_sort_column_id(model.COL_NUMBER) cell.set_property("editable", False) treeview.append_column(column) treeview.set_model(model)
def on_add_button_clicked(self, widget): name = self.view["name_entry"].get_text() number = self.view["number_entry"].get_text() if name == "" or number == "": title = _("Name or number not specified") msg = _("You must provide a valid name and number") dialogs.show_error_dialog(title, msg) widget = (name == "") and "name_entry" or "number_entry" self.view[widget].grab_focus() return self.model.device.Add( name, number, dbus_interface=CTS_INTFACE, reply_handler=self.on_contact_added_cb, error_handler=logger.error ) # save contact till we receive its index, and then we will add # it to the treeview model self.contact = Contact(name, number)
def on_contacts_list_eb(self, error): """ Errback for org.freedesktop.ModemManager.Gsm.Contacts.List Show an error message to the user in case something goes bad """ # end of potentially long operation self.view.stop_throbber() title = _("Error while reading contacts list") dialogs.show_error_dialog(title, get_error_msg(error))
def property_operator_value_change(self, model, old, new): if new == _('Unknown Network'): logger.error("Unknown operator received, using profile name...") profiles_model = self.model.preferences_model.profiles_model try: profile = profiles_model.get_active_profile() except RuntimeError: self.view.operator_changed(new) else: self.view.operator_changed(profile.name) else: self.view.operator_changed(new)
def delete(self): if self.profile: logger.info("Removing profile %s" % self.profile) self.manager.remove_profile(self.profile) self.profile_path = None self.uuid = None self.name = "" while self.sm: sm = self.sm.pop() sm.remove() else: raise RuntimeError(_("Trying to remove an unsaved profile"))
def init_ui(self, ctrl): icon = gtk.image_new_from_stock(gtk.STOCK_CLEAR, gtk.ICON_SIZE_MENU) ctrl.search_entry.set_icon(ICON_ENTRY_SECONDARY, icon) alignment = gtk.Alignment(yalign=MAIN_APP_YALIGN) alignment.add(ctrl.search_entry) self["hbox3"].pack_start(alignment, expand=False) window = self.get_top_widget() window.set_title(_("Manage SMS and Contacts")) window.set_position(gtk.WIN_POS_CENTER_ON_PARENT) window.set_size_request(MAIN_APP_WIDTH, MAIN_APP_HEIGHT) window.set_property("resizable", True)
def __init__(self, parent): flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT super(_KeyringDialog, self).__init__(_("Insert keyring password"), parent, flags) self.cancel_button = self.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT) self.ok_button = self.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) self.ok_button.set_flags(gtk.CAN_DEFAULT) self.ok_button.grab_default() self.ok_button.set_sensitive(False) self.tree = get_tree(FILE_TO_LOAD)
def on_connect_button_toggled(self, widget): dialmanager = self.model.get_dialer_manager() if widget.get_active(): # user wants to connect if not self.model.device: widget.set_active(False) show_warning_dialog( _("No device found"), _("No device has been found. Insert one and try again.")) return profiles_model = self.model.preferences_model.profiles_model if not profiles_model.has_active_profile(): widget.set_active(False) show_warning_dialog( _("Profile needed"), _("You need to create a profile for connecting.")) self.ask_for_new_profile() return active_profile = profiles_model.get_active_profile() dialmanager.ActivateConnection(active_profile.profile_path, self.model.device_opath, timeout=40, reply_handler=self._on_connect_cb, error_handler=self._on_connect_eb) self._setup_connection_signals() def cancel_cb(): self.view.set_disconnected() self.model.dial_path = None def stop_connection_attempt(): self._ignore_no_reply = True dialmanager.StopConnection(self.model.device_opath, reply_handler=cancel_cb, error_handler=logger.error) self.apb = ActivityProgressBar(_("Connecting"), self) self.apb.set_cancel_cb(stop_connection_attempt) self.apb.init() logger.info("Connecting...") else: # user wants to disconnect if not self.model.dial_path: return self.apb = ActivityProgressBar(_("Disconnecting"), self, disable_cancel=True) dialmanager.DeactivateConnection(self.model.dial_path, reply_handler=self._on_disconnect_cb, error_handler=self._on_disconnect_eb) self.apb.init() self.model.dial_path = None
def on_send_toolbutton_clicked(self, widget): numbers = self.view.get_numbers() text = self.view.get_text() if not numbers: title = _("Invalid number") msg = _("You must provide a valid number") dialogs.show_error_dialog(title, msg) self.view["contacts_entry"].grab_focus() return if text == "": title = _("No text to send") msg = _("Are you sure you want to send a blank message?") if not dialogs.show_warning_request_cancel_ok(title, msg): # user cancelled it self.view["text_textview"].grab_focus() return if self.mode == STORAGE and not self.has_changed: # sending from storage sms = self.selected["objs"][0] self.model.device.SendFromStorage( sms.index, dbus_interface=SMS_INTFACE, reply_handler=self.on_sms_sent_cb, error_handler=self.on_sms_sent_eb, ) else: self.state = SENDING for number in numbers: self.model.device.Send( dict(number=number, text=text), dbus_interface=SMS_INTFACE, reply_handler=self.on_sms_sent_cb, error_handler=self.on_sms_sent_eb, ) self.state = IDLE
def load_contacts_model(self, model, ctrl): treeview = self.init_secondary_treeview() cell = gtk.CellRendererText() column = gtk.TreeViewColumn(_("Name"), cell, text=model.COL_NAME) column.set_resizable(True) column.set_sort_column_id(model.COL_NAME) column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) column.set_fixed_width(CTS_NAME_WIDTH) cell.set_property("editable", True) cell.connect("edited", ctrl.on_contact_name_cell_edited) treeview.append_column(column) cell = gtk.CellRendererText() column = gtk.TreeViewColumn(_("Number"), cell, text=model.COL_NUMBER) column.set_resizable(True) column.set_sort_column_id(model.COL_NUMBER) column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) column.set_fixed_width(CTS_NUMBER_WIDTH) cell.set_property("editable", True) cell.connect("edited", ctrl.on_contact_number_cell_edited) treeview.append_column(column) treeview.set_model(model)
def _on_connect_eb(self, e): logger.error("_on_connect_eb: %s" % e) self.view.set_disconnected() if self.apb: self.apb.close() self.apb = None if 'NoReply' in get_error_msg(e) and self._ignore_no_reply: # do not show NoReply exception as we were expecting it self._ignore_no_reply = False elif 'TypeError' in get_error_msg(e) and self._ignore_no_reply: # do not show TypeError exception as we were expecting it # as ActivateConnection returns None instead of an object # path. self._ignore_no_reply = False else: title = _('Failed connection attempt') show_error_dialog(title, get_error_msg(e))
def render_date(cellview, cell, model, _iter, tz): if isinstance(model, gtk.TreeModelFilter): # we are dealing with the filtered model _iter = model.convert_iter_to_child_iter(_iter) model = model.get_model() sms = model.get_value(_iter, model.COL_OBJECT) if sms.datetime is not None: try: delta = datetime.datetime.now(tz) - sms.datetime # show date if more than one day has passed # otherwise, show time of recept fmt = "%x" if delta.days >= 1 else "%X" except TypeError: # dt might be == None fmt = "%x" cell.set_property("text", strftime(fmt, sms.datetime.timetuple())) else: # no datetime, a SMS_SUBMIT cell.set_property("text", _("no timestamp"))
def show_about_dialog(): abt = gtk.AboutDialog() icon = abt.render_icon(gtk.STOCK_ABOUT, gtk.ICON_SIZE_MENU) abt.set_icon(icon) gtk.about_dialog_set_url_hook(lambda abt, url: show_uri(url)) gtk.about_dialog_set_email_hook(lambda d, e: show_uri("mailto:%s" % e)) icon = gtk.gdk.pixbuf_new_from_file(os.path.join(GLADE_DIR, 'wader.png')) abt.set_icon(icon) abt.set_program_name(APP_NAME) abt.set_version(APP_VERSION) abt.set_copyright("Copyright (C) 2008-2009 Wader contributors") abt.set_authors(APP_AUTHORS) abt.set_documenters(APP_DOCUMENTERS) abt.set_artists(APP_ARTISTS) abt.set_website(APP_URL) abt.set_translator_credits(_('translator-credits')) abt.set_website_label(APP_URL) _license = """ The Wader project Copyright (C) 2008-2009 Warp Networks, S.L. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA""" abt.set_license(_license) return abt