class PhotosStock(AbstractMugshotStock): SLIDE_TIMEOUT_SEC = 1 * 60 # 1 minute MAX_PREV_IMAGES = 5 """Cycles between photos from friends in Mugshot network""" def __init__(self, *args, **kwargs): super(PhotosStock, self).__init__(*args, **kwargs) self.__images = None self.__images_reverse = [] self.__images_forward = [] self.__current_image = None self.__box = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL, spacing=4) self.__successive_load_failures = 0 self.__photosize = 120 self.__idle_display_id = 0 self.__text = hippo.CanvasText(text="No thumbnails found") self.__displaymode = "uninitialized" # "none", "photo" self.__displaybox = CanvasVBox(spacing=4) self.__photo_header = CanvasHBox(spacing=4) self.__favicon = CanvasMugshotURLImage() self.__title = ActionLink(size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END) self.__title.connect("button-press-event", lambda photo, event: self.__visit_photo()) self.__photo_header.append(self.__favicon) self.__photo_header.append(self.__title) self.__displaybox.append(self.__photo_header) self.__photobox = CanvasHBox(spacing=6) self.__photo = TransitioningURLImage(dimension=self.__photosize) self.__photo.connect("loaded", lambda photo, loaded: self.__on_image_load(loaded)) self.__photo.connect("button-press-event", lambda photo, event: self.__visit_photo()) self.__metabox = CanvasVBox() self.__metabox.append(hippo.CanvasText(text="from")) self.__fromphoto = CanvasMugshotURLImage() self.__fromphoto.set_clickable(True) self.__fromphoto.connect("button-press-event", lambda photo, event: self.__visit_person()) self.__metabox.append(self.__fromphoto) self.__fromname = ActionLink(size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END) self.__fromname.connect("button-press-event", lambda photo, event: self.__visit_person()) self.__metabox.append(self.__fromname) self.__photobox.append(self.__photo) self.__photobox.append(self.__metabox) self.__displaybox.append(self.__photobox) self.__controlbox = CanvasHBox() prev_link = ActionLink(text=u"\u00ab Prev", xalign=hippo.ALIGNMENT_START) prev_link.connect("button-press-event", lambda b, e: self.__do_prev()) self.__controlbox.append(prev_link) next_link = ActionLink(text=u"Next \u00bb", xalign=hippo.ALIGNMENT_END) next_link.connect("button-press-event", lambda b, e: self.__do_next()) self.__controlbox.append(next_link, hippo.PACK_EXPAND) self.__displaybox.append(self.__controlbox) self.__person_accts_len = {} # <Person,int> self.__bearbox = CanvasVBox() self.__bearphoto = TransitioningURLImage(dimension=self.SIZE_BEAR_CONTENT_PX - 6) self.__bearphoto.connect("button-press-event", lambda photo, event: self.__visit_photo()) self.__bearbox.append(self.__bearphoto) def _on_ready(self): if self._model.self_resource != None: query = self._model.query_resource( self._model.self_resource, "contacts user [+;lovedAccounts [+;thumbnails +]]" ) query.add_handler(self.__on_got_self) query.execute() def __on_got_self(self, myself): self.__reset() def get_authed_content(self, size): return size == self.SIZE_BULL and self.__box or self.__bearbox def __visit_photo(self): _logger.debug("visiting photo for %s", self.__current_image) if not self.__current_image: return libbig.show_url(self.__current_image[2].get_href()) def __visit_person(self): _logger.debug("visiting person for %s", self.__current_image) if not self.__current_image: return libbig.show_url(urlparse.urljoin(globals.get_baseurl(), self.__current_image[0].get_home_url())) def __thumbnails_generator(self): """The infinite photos function. Cool.""" while True: found_one = False # Iterate through all thumbnails for all "loved accounts" for all contacts. # We don't handle change notification ... if something changes we'll pick # it up next time around. Note the use of temporary copies of lists to avoid # problems if a list is mutated by a change notification while we are iterating it. if self._model.self_resource: for contact in list(getattr(self._model.self_resource, "contacts", [])): user = getattr(contact, "user", None) if user != None: lovedAccounts = getattr(user, "lovedAccounts", None) if lovedAccounts: for externalAccount in lovedAccounts: thumbnails = getattr(externalAccount, "thumbnails", None) if thumbnails: for thumbnail in thumbnails: yield (user, externalAccount, thumbnail) # If we didn't find any photos, we go into a "no photos" state; we'll keep on trying # to restart the iterator in the timeout, so when things appear we'll display them if not found_one: return def __next_image(self): if self.__current_image: self.__images_reverse.append(self.__current_image) if len(self.__images_reverse) > self.MAX_PREV_IMAGES: self.__images_reverse.pop(0) if self.__images_forward: return self.__images_forward.pop() else: return self.__images.next() def __prev_image(self): if self.__current_image: self.__images_forward.append(self.__current_image) return self.__images_reverse.pop() def __set_image(self, imageinfo): self.__current_image = imageinfo (user, account, thumbnail) = imageinfo _logger.debug("starting load of url %s" % (thumbnail.src,)) self.__photo.set_url(thumbnail.src) self.__bearphoto.set_url(thumbnail.src) def __on_image_load(self, success): if self.__current_image is None: _logger.debug("image load complete, but no current image") return if not success: self.__successive_load_failures = max(self.__successive_load_failures + 1, 17) _logger.debug("image load failed, queueing skip to next") gobject.timeout_add(8000 + (2 ** self.__successive_load_failures) * 1000, self.__do_next) else: self.__successive_load_failures = 0 _logger.debug("image load success, syncing metadata") (user, account, thumbnail) = self.__current_image self.__favicon.set_url(account.iconUrl) title = getattr(thumbnail, "title", None) if not title: title = "(untitled)" self.__title.set_property("text", title) self.__fromname.set_property("text", user.name) self.__fromphoto.set_url(user.photoUrl) def __idle_display_image(self): _logger.debug("in idle, doing next image") self.__idle_display_id = 0 self.__do_next() return False def __do_direction(self, is_next): _logger.debug("skipping to %s" % (is_next and "next" or "prev",)) try: self.__set_image(is_next and self.__next_image() or self.__prev_image()) if self.__displaymode == "text": self.__box.remove(self.__text) if self.__displaymode != "photo": self.__box.append(self.__displaybox) self.__displaymode = "photo" except StopIteration: _logger.debug("caught StopIteration, displaying no photos text") if self.__displaymode == "photo": self.__box.remove(self.__displaybox) if self.__displaymode != "text": self.__box.append(self.__text) self.__displaymode = "text" if self.__idle_display_id > 0: gobject.source_remove(self.__idle_display_id) self.__idle_display_id = gobject.timeout_add(self.SLIDE_TIMEOUT_SEC * 1000, self.__idle_display_image) def __do_next(self): self.__do_direction(True) def __do_prev(self): self.__do_direction(False) def __reset(self): _logger.debug("resetting") self.__images = self.__thumbnails_generator() self.__images_reverse = [] self.__box.remove_all() self.__displaymode = "uninitialized" self.__do_next()
class PhotosStock(AbstractMugshotStock): SLIDE_TIMEOUT_SEC = 1 * 60 # 1 minute MAX_PREV_IMAGES = 5 """Cycles between photos from friends in Mugshot network""" def __init__(self, *args, **kwargs): super(PhotosStock,self).__init__(*args, **kwargs) self.__images = None self.__images_reverse = [] self.__images_forward = [] self.__current_image = None self.__box = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL, spacing=4) self.__successive_load_failures = 0 self.__photosize = 120 self.__idle_display_id = 0 self.__text = hippo.CanvasText(text="No thumbnails found") self.__displaymode = "uninitialized" # "none", "photo" self.__displaybox = CanvasVBox(spacing=4) self.__photo_header = CanvasHBox(spacing=4) self.__favicon = CanvasMugshotURLImage() self.__title = ActionLink(size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END) self.__title.connect("button-press-event", lambda photo, event: self.__visit_photo()) self.__photo_header.append(self.__favicon) self.__photo_header.append(self.__title) self.__displaybox.append(self.__photo_header) self.__photobox = CanvasHBox(spacing=6) self.__photo = TransitioningURLImage(self._logger, dimension=self.__photosize) self.__photo.connect("loaded", lambda photo, loaded: self.__on_image_load(loaded)) self.__photo.connect("button-press-event", lambda photo, event: self.__visit_photo()) self.__metabox = CanvasVBox() self.__metabox.append(hippo.CanvasText(text="from")) self.__fromphoto = CanvasMugshotURLImage() self.__fromphoto.set_clickable(True) self.__fromphoto.connect("button-press-event", lambda photo, event: self.__visit_person()) self.__metabox.append(self.__fromphoto) self.__fromname = ActionLink(size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END) self.__fromname.connect("button-press-event", lambda photo, event: self.__visit_person()) self.__metabox.append(self.__fromname) self.__photobox.append(self.__photo) self.__photobox.append(self.__metabox) self.__displaybox.append(self.__photobox) self.__controlbox = CanvasHBox() prev_link = ActionLink(text=u"\u00ab Prev", xalign=hippo.ALIGNMENT_START) prev_link.connect("button-press-event", lambda b,e: self.__do_prev()) self.__controlbox.append(prev_link) next_link = ActionLink(text=u"Next \u00bb", xalign=hippo.ALIGNMENT_END) next_link.connect("button-press-event", lambda b,e: self.__do_next()) self.__controlbox.append(next_link, hippo.PACK_EXPAND) self.__displaybox.append(self.__controlbox) self.__person_accts_len = {} # <Person,int> self.__bearbox = CanvasVBox() self.__bearphoto = TransitioningURLImage(self._logger, dimension=self.SIZE_BEAR_CONTENT_PX-6) self.__bearphoto.connect("button-press-event", lambda photo, event: self.__visit_photo()) self.__bearbox.append(self.__bearphoto) self._mugshot.connect("network-changed", lambda mugshot: self.__handle_network_change()) def _on_mugshot_ready(self): super(PhotosStock, self)._on_mugshot_ready() self._mugshot.get_network() def get_authed_content(self, size): return size == self.SIZE_BULL and self.__box or self.__bearbox def __visit_photo(self): self._logger.debug("visiting photo for %s", self.__current_image) if not self.__current_image: return libbig.show_url(self.__current_image[2].get_href()) def __visit_person(self): self._logger.debug("visiting person for %s", self.__current_image) if not self.__current_image: return libbig.show_url(mugshot.get_mugshot().get_baseurl() + self.__current_image[0].get_home_url()) def __thumbnails_generator(self): """The infinite photos function. Cool.""" found_one = False while True: for entity in self._mugshot.get_network(): accts = entity.get_external_accounts() if not accts: continue for acct in accts: if acct.get_thumbnails(): for thumbnail in acct.get_thumbnails(): found_one = True yield (entity, acct, thumbnail) if not found_one: return def __next_image(self): if self.__current_image: self.__images_reverse.append(self.__current_image) if len(self.__images_reverse) > self.MAX_PREV_IMAGES: self.__images_reverse.pop(0) if self.__images_forward: return self.__images_forward.pop() else: return self.__images.next() def __prev_image(self): if self.__current_image: self.__images_forward.append(self.__current_image) return self.__images_reverse.pop() def __set_image(self, imageinfo): self.__current_image = imageinfo (entity, acct, thumbnail) = imageinfo self._logger.debug("starting load of url %s" % (thumbnail.get_src(),)) self.__photo.set_url(thumbnail.get_src()) self.__bearphoto.set_url(thumbnail.get_src()) def __on_image_load(self, success): if self.__current_image is None: self._logger.debug("image load complete, but no current image") return if not success: self.__successive_load_failures = max(self.__successive_load_failures+1, 17) self._logger.debug("image load failed, queueing skip to next") gobject.timeout_add(8000 + (2 ** self.__successive_load_failures) * 1000, self.__do_next) else: self.__successive_load_failures = 0 self._logger.debug("image load success, syncing metadata") (entity, acct, thumbnail) = self.__current_image self.__favicon.set_url(acct.get_icon()) self.__title.set_property("text", thumbnail.get_title() or "(untitled)") self.__fromname.set_property("text", entity.get_name()) self.__fromphoto.set_url(entity.get_photo_url()) def __idle_display_image(self): self._logger.debug("in idle, doing next image") self.__idle_display_id = 0 self.__do_next() return False def __handle_person_change(self, person): need_reset = False accts = person.get_external_accounts() if not self.__person_accts_len.has_key(person): need_reset = True self.__person_accts_len[person] = -1 elif accts and self.__person_accts_len[person] != len(accts): self.__person_accts_len[person] = len(accts) need_reset = True if need_reset: self.__reset() def __handle_network_change(self): self._logger.debug("handling network change") for person in self._mugshot.get_network(): if not self.__person_accts_len.has_key(person): person.connect("changed", self.__handle_person_change) accts = person.get_external_accounts() self.__person_accts_len[person] = accts and len(accts) or 0 not_in_network = [] for person in self.__person_accts_len.iterkeys(): if not person in self._mugshot.get_network(): not_in_network.append(person) for person in not_in_network: self._logger.debug("removing not-in-network person %s", person.get_guid()) del self.__person_accts_len[person] self.__reset() def __do_direction(self, is_next): self._logger.debug("skipping to %s" % (is_next and "next" or "prev",)) try: self.__set_image(is_next and self.__next_image() or self.__prev_image()) if self.__displaymode == 'text': self.__box.remove(self.__text) if self.__displaymode != 'photo': self.__box.append(self.__displaybox) self.__displaymode = 'photo' except StopIteration: self._logger.debug("caught StopIteration, displaying no photos text") if self.__displaymode == 'photo': self.__box.remove(self.__displaybox) if self.__displaymode != 'text': self.__box.append(self.__text) self.__displaymode = 'text' if self.__idle_display_id > 0: gobject.source_remove(self.__idle_display_id) self.__idle_display_id = gobject.timeout_add(self.SLIDE_TIMEOUT_SEC * 1000, self.__idle_display_image) def __do_next(self): self.__do_direction(True) def __do_prev(self): self.__do_direction(False) def __reset(self): self._logger.debug("resetting") self.__images = self.__thumbnails_generator() self.__box.remove_all() self.__displaymode = 'uninitialized' self.__do_next()
class ProfileItem(hippo.CanvasBox): __gsignals__ = { "close": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (bool,)) } def __init__(self, person, themed=False, **kwargs): kwargs['orientation'] = hippo.ORIENTATION_VERTICAL hippo.CanvasBox.__init__(self, **kwargs) self.person = person self.__themed = themed if themed: self.__header = Header(topborder=False) else: self.__header = hippo.CanvasGradient(orientation=hippo.ORIENTATION_HORIZONTAL, start_color=0xf2f2f2f2, end_color=0xc8c8c8ff) self.append(self.__header) textklass = themed and ThemedText or hippo.CanvasText linkklass = themed and ThemedLink or ActionLink name_vbox = hippo.CanvasBox(padding=6) self.__name = textklass(font="22px") name_vbox.append(self.__name) rename_link = linkklass(text='rename', font="10px", xalign=hippo.ALIGNMENT_END) name_vbox.append(rename_link) rename_link.connect('activated', self.__on_rename_activated) self.__header.append(name_vbox) if person.is_contact: try: user = person.resource.user except AttributeError: user = None if user: mugshot_link = linkklass(text="Mugshot", padding=6) self.__header.append(mugshot_link, flags=hippo.PACK_END) mugshot_link.connect("activated", self.__on_activate_web) self.__top_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL) self.append(self.__top_box) self.__photo = CanvasMugshotURLImage(scale_width=60, scale_height=60, border=5) if person.is_contact: try: user = person.resource.user except AttributeError: user = None if user: self.__photo.set_clickable(True) self.__photo.connect("activated", self.__on_activate_web) self.__top_box.append(self.__photo) self.__address_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL) self.__top_box.append(self.__address_box) self.__contact_status_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL, spacing=4, border=4) self.append(self.__contact_status_box) if person.is_contact: self.__add_link = None self.__remove_link = linkklass() self.__remove_link.connect('activated', self.__remove_from_network_clicked) self.append(self.__remove_link) else: self.__remove_link = None self.__add_link = linkklass(text=('Add %s to network' % self.person.display_name)) self.__add_link.connect('activated', self.__add_to_network_clicked) self.append(self.__add_link) # self.__online = hippo.CanvasText(text='Offline') # self.append(self.__online) separator = hippo.CanvasBox(box_height=1, background_color=0xAAAAAAFF) self.append(separator) self.__ribbon_bar = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL, spacing=2, border=4) self.append(self.__ribbon_bar) self.__link_box = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL, spacing=2, border=4) self.append(self.__link_box) self.__local_files_link = None self.person.connect('display-name-changed', self.__update) self.person.connect('icon-url-changed', self.__update) self.person.connect('aim-changed', self.__update) self.person.connect('local-buddy-changed', self.__update_local_buddy) self.person.connect('xmpp-changed', self.__update) if person.is_contact: self.person.resource.connect(lambda *args: self.__update(self.person), 'emails') self.person.resource.connect(self.__update_contact_status, "status") try: user = person.resource.user except AttributeError: user = None if user: user.connect(self.__update_loved_accounts, "lovedAccounts") query = DataModel(bigboard.globals.server_name).query_resource(self.person.resource, "lovedAccounts +") query.add_handler(self.__update_loved_accounts) query.execute() self.__update(self.person) self.__update_local_buddy(self.person) if self.person.is_contact: self.__update_contact_status(self.person.resource) try: user = person.resource.user except AttributeError: user = None if user: self.__update_loved_accounts(user) def __add_status_link(self, text, current_status, new_status): textklass = self.__themed and ThemedText or hippo.CanvasText linkklass = self.__themed and ThemedLink or ActionLink if current_status == new_status: link = textklass(text=text) else: def set_new_status(object): model = globals.get_data_model() query = model.update(("http://mugshot.org/p/contacts", "setContactStatus"), contact=self.person.resource, status=new_status) query.execute() link = linkklass(text=text) link.connect("activated", set_new_status) self.__contact_status_box.append(link) def __remove_from_network_clicked(self, link): dialog = gtk.MessageDialog(type=gtk.MESSAGE_QUESTION) dialog.set_markup("<b>Remove %s from your network?</b>" % (self.person.display_name)) dialog.format_secondary_text("This will delete %s's contact information and remove %s from your sidebar" % (self.person.display_name, self.person.display_name)) dialog.add_buttons("Cancel", gtk.RESPONSE_CANCEL, "Remove", gtk.RESPONSE_ACCEPT) def remove_from_network_response(dialog, response_id, person): dialog.destroy() if response_id == gtk.RESPONSE_ACCEPT: _logger.debug("removing from network") model = globals.get_data_model() query = model.update(("http://mugshot.org/p/contacts", "deleteContact"), contact=person.resource) query.execute() else: _logger.debug("not removing from network") dialog.connect("response", lambda dialog, response_id: remove_from_network_response(dialog, response_id, self.person)) # action_taken = False to leave the stock open which seems nicer in this case self.emit("close", False) dialog.show() def __on_rename_activated(self, link): dialog = gtk.Dialog(title="Rename a contact") entry = gtk.Entry() entry.set_text(self.person.display_name) entry.set_activates_default(True) hbox = gtk.HBox(spacing=10) hbox.pack_start(gtk.Label('Name:'), False, False) hbox.pack_end(entry, True, True) hbox.show_all() dialog.vbox.pack_start(hbox) dialog.add_buttons("Cancel", gtk.RESPONSE_CANCEL, "Rename", gtk.RESPONSE_ACCEPT) dialog.set_default_response(gtk.RESPONSE_ACCEPT) def rename_response(dialog, response_id, person): dialog.destroy() if response_id == gtk.RESPONSE_ACCEPT: _logger.debug("renaming this person") name = entry.get_text() model = globals.get_data_model() query = model.update(("http://mugshot.org/p/contacts", "setContactName"), contact=person.resource, name=name) query.execute() else: _logger.debug("not renaming") dialog.connect("response", lambda dialog, response_id: rename_response(dialog, response_id, self.person)) # action_taken = False to leave the stock open which seems nicer in this case self.emit("close", False) dialog.show() def __create_contact(self, addressType, address): _logger.debug("creating contact %s %s" % (addressType, address)) model = globals.get_data_model() query = model.update(("http://mugshot.org/p/contacts", "createContact"), addressType=addressType, address=address) query.execute() def __create_user_contact(self, user_resource): _logger.debug("creating contact %s" % (str(user_resource))) model = globals.get_data_model() query = model.update(("http://mugshot.org/p/contacts", "createUserContact"), user=user_resource); query.execute() def __add_to_network_clicked(self, link): if self.person.aim: self.__create_contact('aim', self.person.aim) elif self.person.xmpp: self.__create_contact('xmpp', self.person.xmpp) elif self.person.local_buddy: self.__create_user_contact(self.person.local_buddy.user) # action_taken = False to leave the stock open which seems nicer in this case self.emit("close", False) def __update_contact_status(self, person): self.__contact_status_box.remove_all() try: status = self.person.resource.status except AttributeError: status = 0 if status == 0: status = 3 textklass = self.__themed and ThemedText or hippo.CanvasText self.__contact_status_box.append(textklass(text="In sidebar: ")) self.__add_status_link("Top", status, 4) self.__add_status_link("Middle", status, 3) self.__add_status_link("Bottom", status, 2) def __update_loved_accounts(self, person): try: accounts = self.person.resource.lovedAccounts except AttributeError: accounts = [] self.__ribbon_bar.clear() for a in accounts: icon = ExternalAccountIcon(a) self.__ribbon_bar.append(icon) def __update_local_buddy(self, person): if self.__local_files_link: self.__local_files_link.destroy() self.__local_files_link = None try: buddy = person.local_buddy except AttributeError: return if buddy != None: self.__local_files_link = LocalFilesLink(buddy) self.__link_box.append(self.__local_files_link) def __update(self, person): textklass = self.__themed and ThemedText or hippo.CanvasText linkklass = self.__themed and ThemedLink or ActionLink self.__name.set_property('text', self.person.display_name) self.__photo.set_url(self.person.icon_url) self.__address_box.remove_all() if self.__remove_link: self.__remove_link.set_property('text', "Remove %s from network" % self.person.display_name) emails = None if person.is_contact: try: emails = self.person.resource.emails except AttributeError: pass if emails != None and len(emails) > 0: email = linkklass(text=emails[0], xalign=hippo.ALIGNMENT_START) email.connect('activated', self.__on_activate_email) self.__address_box.append(email) if person.aim != None: aim = linkklass(text=person.aim, xalign=hippo.ALIGNMENT_START) aim.connect('activated', self.__on_activate_aim) self.__address_box.append(aim) if person.xmpp != None: xmpp = linkklass(text=person.aim, xalign=hippo.ALIGNMENT_START) xmpp.connect('activated', self.__on_activate_xmpp) self.__address_box.append(xmpp) add = linkklass(text='add address', xalign=hippo.ALIGNMENT_END, font_scale=0.8) add.connect('activated', self.__on_activate_add_address) self.__address_box.append(add) def __on_activate_web(self, canvas_item): self.emit("close", True) libbig.show_url(self.person.resource.user.homeUrl) def __on_activate_email(self, canvas_item): self.emit("close", True) # email should probably cgi.escape except it breaks if you escape the @ os.spawnlp(os.P_NOWAIT, 'gnome-open', 'gnome-open', 'mailto:' + self.person.resource.email) def __on_activate_aim(self, canvas_item): self.emit("close", True) _open_aim(self.person.aim) def __on_activate_xmpp(self, canvas_item): self.emit("close", True) _open_xmpp(self.person.xmpp) def __on_activate_add_address(self, canvas_item): dialog = gtk.Dialog(title=("Add an address for %s" % self.person.display_name)) entry = gtk.Entry() entry.set_activates_default(True) hbox = gtk.HBox(spacing=10) hbox.pack_start(gtk.Label('Address:'), False, False) hbox.pack_end(entry, True, True) hbox.show_all() dialog.vbox.pack_start(hbox) type_combo = gtk.combo_box_new_text() type_combo.append_text('AIM') type_combo.append_text('Email') type_combo.append_text('GTalk/XMPP') type_combo.set_active(0) hbox = gtk.HBox(spacing=10) hbox.pack_start(gtk.Label('Type:'), False, False) hbox.pack_end(type_combo, True, True) hbox.show_all() dialog.vbox.pack_start(hbox) dialog.add_buttons("Cancel", gtk.RESPONSE_CANCEL, "Add", gtk.RESPONSE_ACCEPT) dialog.set_default_response(gtk.RESPONSE_ACCEPT) def combo_get_address_type(combo): visible_type = type_combo.get_active_text() addressType = None if visible_type == 'Email': addressType = 'email' elif visible_type == 'AIM': addressType = 'aim' elif visible_type == 'GTalk/XMPP': addressType = xmpp else: _logger.warn('Bug: unknown combox box text for address type') if '@' in entry.get_text(): addressType = 'email' else: addressType = 'aim' return addressType def address_entry_changed(entry): address = entry.get_text() type = combo_get_address_type(type_combo) if '@' in address and type == 'aim': type_combo.set_active(1) ## set to email if an @ is typed elif '@' not in address and type == 'email': type_combo.set_active(0) ## set to AIM if no @ is found ## remember that @ can mean either email or xmpp entry.connect('changed', address_entry_changed) def add_address_response(dialog, response_id, person): dialog.destroy() if response_id == gtk.RESPONSE_ACCEPT: _logger.debug("adding address for this person") address = entry.get_text() addressType = combo_get_address_type(type_combo) model = globals.get_data_model() query = model.update(("http://mugshot.org/p/contacts", "addContactAddress"), contact=person.resource, addressType=addressType, address=address) query.execute() else: _logger.debug("not adding_address") dialog.connect("response", lambda dialog, response_id: add_address_response(dialog, response_id, self.person)) # action_taken = False to leave the stock open which seems nicer in this case self.emit("close", False) dialog.show()