def get_avatar_pixbuf_encoded_mime(photo): """ Return the pixbuf of the image Photo is a dictionary containing PHOTO information. """ if not isinstance(photo, dict): return None, None, None img_decoded = None avatar_encoded = None avatar_mime_type = None if 'BINVAL' in photo: img_encoded = photo['BINVAL'] avatar_encoded = img_encoded try: img_decoded = base64.decodestring(img_encoded) except Exception: pass if img_decoded: if 'TYPE' in photo: avatar_mime_type = photo['TYPE'] pixbuf = gtkgui_helpers.get_pixbuf_from_data(img_decoded) else: pixbuf, avatar_mime_type = gtkgui_helpers.get_pixbuf_from_data( img_decoded, want_type=True) else: pixbuf = None return pixbuf, avatar_encoded, avatar_mime_type
def get_avatar_pixbuf_encoded_mime(photo): """ Return the pixbuf of the image Photo is a dictionary containing PHOTO information. """ if not isinstance(photo, dict): return None, None, None img_decoded = None avatar_encoded = None avatar_mime_type = None if 'BINVAL' in photo: img_encoded = photo['BINVAL'] avatar_encoded = img_encoded try: img_decoded = base64.b64decode(img_encoded.encode('utf-8')) except Exception: pass if img_decoded: if 'TYPE' in photo: avatar_mime_type = photo['TYPE'] pixbuf = gtkgui_helpers.get_pixbuf_from_data(img_decoded) else: pixbuf, avatar_mime_type = gtkgui_helpers.get_pixbuf_from_data( img_decoded, want_type=True) else: pixbuf = None return pixbuf, avatar_encoded, avatar_mime_type
def get_avatar_pixbuf_encoded_mime(photo): '''return the pixbuf of the image photo is a dictionary containing PHOTO information''' if not isinstance(photo, dict): return None, None, None img_decoded = None avatar_encoded = None avatar_mime_type = None if photo.has_key('BINVAL') and photo.has_key('TYPE'): img_encoded = photo['BINVAL'] avatar_encoded = img_encoded avatar_mime_type = photo['TYPE'] try: img_decoded = base64.decodestring(img_encoded) except: pass elif photo.has_key('EXTVAL'): url = photo['EXTVAL'] try: fd = urllib.urlopen(url) img_decoded = fd.read() except: pass if img_decoded: pixbuf = gtkgui_helpers.get_pixbuf_from_data(img_decoded) else: pixbuf = None return pixbuf, avatar_encoded, avatar_mime_type
def on_set_avatar_button_clicked(self, widget): def on_ok(widget, path_to_file): must_delete = False filesize = os.path.getsize(path_to_file) # in bytes invalid_file = False msg = '' if os.path.isfile(path_to_file): stat = os.stat(path_to_file) if stat[6] == 0: invalid_file = True msg = _('File is empty') else: invalid_file = True msg = _('File does not exist') if not invalid_file and filesize > 16384: # 16 kb try: pixbuf = gtk.gdk.pixbuf_new_from_file(path_to_file) # get the image at 'notification size' # and hope that user did not specify in ACE crazy size scaled_pixbuf = gtkgui_helpers.get_scaled_pixbuf( pixbuf, 'tooltip') except gobject.GError, msg: # unknown format # msg should be string, not object instance msg = str(msg) invalid_file = True if invalid_file: if True: # keep identation dialogs.ErrorDialog(_('Could not load image'), msg) return if filesize > 16384: if scaled_pixbuf: path_to_file = os.path.join(gajim.TMP, 'avatar_scaled.png') scaled_pixbuf.save(path_to_file, 'png') must_delete = True fd = open(path_to_file, 'rb') data = fd.read() pixbuf = gtkgui_helpers.get_pixbuf_from_data(data) try: # rescale it pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'vcard') except AttributeError: # unknown format dialogs.ErrorDialog(_('Could not load image')) return self.dialog.destroy() self.dialog = None button = self.xml.get_widget('PHOTO_button') image = button.get_image() image.set_from_pixbuf(pixbuf) button.show() text_button = self.xml.get_widget('NOPHOTO_button') text_button.hide() self.avatar_encoded = base64.encodestring(data) # returns None if unknown type self.avatar_mime_type = mimetypes.guess_type(path_to_file)[0] if must_delete: try: os.remove(path_to_file) except OSError: gajim.log.debug('Cannot remove %s' % path_to_file)
def on_event_added(self, event): account = event.account jid = event.jid when = time.localtime() contact = "" key = (account, jid) if event.type_ == "chat" or \ event.type_ == "printed_chat" or \ event.type_ == "normal" or \ event.type_ == "printed_normal" or \ event.type_ == "file-request" or \ event.type_ == "jingle-incoming": contact = gajim.contacts.get_contact_from_full_jid(account, jid) if contact: contact = contact.get_shown_name() else: contact = jid elif event.type_ == "pm" or event.type_ == "printed_pm": contact = gajim.get_nick_from_jid(gajim.get_room_from_fjid(jid)) + \ "/" + gajim.get_room_and_nick_from_fjid(jid)[1] elif event.type_ == "printed_marked_gc_msg": contact = gajim.get_nick_from_jid(gajim.get_room_from_fjid(jid)) else: return #print account, jid, when, contact event.time = when if key not in self.events: icon = None if gajim.config.get("show_avatars_in_roster"): pixbuf = gtkgui_helpers.get_avatar_pixbuf_from_cache(jid) if pixbuf not in (None, "ask"): icon = gtk.Image() icon.set_from_pixbuf(pixbuf) else: file_path = gtkgui_helpers.get_path_to_generic_or_avatar(jid) if os.path.isfile(file_path): fd = fopen(file_path, 'rb') data = fd.read() icon = gtk.Image() icon.set_from_pixbuf(gtkgui_helpers.get_pixbuf_from_data(data)) item = gtk.ImageMenuItem(contact + " (1)") if icon: item.set_image(icon) item.set_always_show_image(True) item.connect("activate", self.event_raise, event) item.show() self.menu.insert(item, self.menuEventInsertIndex) self.event_separator.show() self.events[key] = {} self.events[key]['item'] = item self.events[key]['contact'] = contact self.events[key]['events'] = [event] else: self.events[key]['events'].append(event) item = self.events[key]['item'] item.set_label(self.events[key]['contact'] + " (" + str(len(self.events[key]['events'])) + ")") self.indicator.set_status(appindicator.STATUS_ATTENTION)
def on_set_avatar_button_clicked(self, widget): def on_ok(widget, path_to_file): must_delete = False filesize = os.path.getsize(path_to_file) # in bytes invalid_file = False msg = "" if os.path.isfile(path_to_file): stat = os.stat(path_to_file) if stat[6] == 0: invalid_file = True msg = _("File is empty") else: invalid_file = True msg = _("File does not exist") if not invalid_file and filesize > 16384: # 16 kb try: pixbuf = gtk.gdk.pixbuf_new_from_file(path_to_file) # get the image at 'notification size' # and hope that user did not specify in ACE crazy size scaled_pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, "tooltip") except gobject.GError, msg: # unknown format # msg should be string, not object instance msg = str(msg) invalid_file = True if invalid_file: if True: # keep identation dialogs.ErrorDialog(_("Could not load image"), msg) return if filesize > 16384: if scaled_pixbuf: path_to_file = os.path.join(gajim.TMP, "avatar_scaled.png") scaled_pixbuf.save(path_to_file, "png") must_delete = True fd = open(path_to_file, "rb") data = fd.read() pixbuf = gtkgui_helpers.get_pixbuf_from_data(data) try: # rescale it pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, "vcard") except AttributeError: # unknown format dialogs.ErrorDialog(_("Could not load image")) return self.dialog.destroy() self.dialog = None button = self.xml.get_widget("PHOTO_button") image = button.get_image() image.set_from_pixbuf(pixbuf) button.show() text_button = self.xml.get_widget("NOPHOTO_button") text_button.hide() self.avatar_encoded = base64.encodestring(data) # returns None if unknown type self.avatar_mime_type = mimetypes.guess_type(path_to_file)[0] if must_delete: try: os.remove(path_to_file) except OSError: gajim.log.debug("Cannot remove %s" % path_to_file)
def on_event_added(self, event): account = event.account jid = event.jid when = time.time() contact = "" key = (account, jid) if event.type_ == "chat" or \ event.type_ == "printed_chat" or \ event.type_ == "normal" or \ event.type_ == "printed_normal" or \ event.type_ == "file-request" or \ event.type_ == "jingle-incoming": contact = gajim.contacts.get_contact_from_full_jid(account, jid) if contact: contact = contact.get_shown_name() else: contact = jid elif event.type_ == "pm" or event.type_ == "printed_pm": contact = gajim.get_nick_from_jid(gajim.get_room_from_fjid(jid)) + \ "/" + gajim.get_room_and_nick_from_fjid(jid)[1] elif event.type_ == "printed_marked_gc_msg": contact = gajim.get_nick_from_jid(gajim.get_room_from_fjid(jid)) else: return #print account, jid, when, contact event.time = when if key not in self.events: icon = None if gajim.config.get("show_avatars_in_roster"): pixbuf = gtkgui_helpers.get_avatar_pixbuf_from_cache(jid) if pixbuf not in (None, "ask"): icon = gtk.Image() icon.set_from_pixbuf(pixbuf) else: file_path = gtkgui_helpers.get_path_to_generic_or_avatar(jid) if os.path.isfile(file_path): fd = fopen(file_path, 'rb') data = fd.read() icon = gtk.Image() icon.set_from_pixbuf(gtkgui_helpers.get_pixbuf_from_data(data)) item = gtk.ImageMenuItem(contact + " (1)") if icon: item.set_image(icon) item.set_always_show_image(True) item.connect("activate", self.event_raise, event) item.show() self.menu.insert(item, self.menuEventInsertIndex) self.event_separator.show() self.events[key] = {} self.events[key]['item'] = item self.events[key]['contact'] = contact self.events[key]['events'] = [event] else: self.events[key]['events'].append(event) item = self.events[key]['item'] item.set_label(self.events[key]['contact'] + " (" + str(len(self.events[key]['events'])) + ")") self.indicator.set_status(appindicator.STATUS_ATTENTION)
def on_set_avatar_button_clicked(self, widget): f = None dialog = gtk.FileChooserDialog(_('Choose Avatar'), None, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) dialog.set_default_response(gtk.RESPONSE_OK) filtr = gtk.FileFilter() filtr.set_name(_('All files')) filtr.add_pattern('*') dialog.add_filter(filtr) filtr = gtk.FileFilter() filtr.set_name(_('Images')) filtr.add_mime_type('image/png') filtr.add_mime_type('image/jpeg') filtr.add_mime_type('image/gif') filtr.add_mime_type('image/tiff') filtr.add_mime_type('image/x-xpixmap') # xpm dialog.add_filter(filtr) dialog.set_filter(filtr) dialog.set_use_preview_label(False) dialog.set_preview_widget(gtk.Image()) dialog.connect('selection-changed', self.update_preview) done = False while not done: response = dialog.run() if response == gtk.RESPONSE_OK: f = dialog.get_filename() try: f = f.decode(sys.getfilesystemencoding()) except UnicodeError: pass else: filesize = os.path.getsize(f) # in bytes if filesize > 32768: # 32 kb dialogs.ErrorDialog(_('The filesize of image "%s" is too large')\ % os.path.basename(f), _('The file must not be more than 32 kilobytes.')).get_response() continue if self.image_is_ok(f): done = True else: # Cancel or WM X button done = True dialog.destroy() if response == gtk.RESPONSE_OK: fd = open(f, 'rb') data = fd.read() pixbuf = gtkgui_helpers.get_pixbuf_from_data(data) image = self.xml.get_widget('PHOTO_image') image.set_from_pixbuf(pixbuf) self.avatar_encoded = base64.encodestring(data) # returns None if unknown type self.avatar_mime_type = mimetypes.guess_type(f)[0]
def populate(self, contact): """ Populate the Tooltip Grid with data of from the contact """ self.clear_tooltip() self.nick.set_text(contact.get_shown_name()) self.nick.show() # Status Message if contact.status: status = contact.status.strip() if status != '': self.status.set_text(status) self.status.show() # Status show = helpers.get_uf_show(contact.show) self.user_show.set_markup(colorize_status(show)) self.user_show.show() # JID if contact.jid.strip(): self.jid.set_text(contact.jid) self.jid.show() self.jid_label.show() # Resource if hasattr(contact, 'resource') and contact.resource.strip(): self.resource.set_text(contact.resource) self.resource.show() self.resource_label.show() # Affiliation if contact.affiliation != 'none': uf_affiliation = helpers.get_uf_affiliation(contact.affiliation) uf_affiliation = \ _('%(owner_or_admin_or_member)s of this group chat') \ % {'owner_or_admin_or_member': uf_affiliation} uf_affiliation = self.colorize_affiliation(uf_affiliation) self.affiliation.set_markup(uf_affiliation) self.affiliation.show() # Avatar puny_name = helpers.sanitize_filename(contact.name) puny_room = helpers.sanitize_filename(contact.room_jid) file_ = helpers.get_avatar_path(os.path.join(gajim.AVATAR_PATH, puny_room, puny_name)) if file_: with open(file_, 'rb') as file_data: pix = gtkgui_helpers.get_pixbuf_from_data(file_data.read()) pix = gtkgui_helpers.get_scaled_pixbuf(pix, 'tooltip') self.avatar.set_from_pixbuf(pix) self.avatar.show() self.fillelement.show()
def on_ok(widget, path_to_file): must_delete = False filesize = os.path.getsize(path_to_file) # in bytes invalid_file = False msg = '' if os.path.isfile(path_to_file): stat = os.stat(path_to_file) if stat[6] == 0: invalid_file = True msg = _('File is empty') else: invalid_file = True msg = _('File does not exist') if not invalid_file and filesize > 16384: # 16 kb try: pixbuf = GdkPixbuf.Pixbuf.new_from_file(path_to_file) # get the image at 'notification size' # and hope that user did not specify in ACE crazy size scaled_pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'tooltip') except GObject.GError as msg: # unknown format # msg should be string, not object instance msg = str(msg) invalid_file = True if invalid_file: if True: # keep identation dialogs.ErrorDialog(_('Could not load image'), msg, transient_for=self.window) return if filesize > 16384: if scaled_pixbuf: path_to_file = os.path.join(gajim.TMP, 'avatar_scaled.png') scaled_pixbuf.savev(path_to_file, 'png', [], []) must_delete = True with open(path_to_file, 'rb') as fd: data = fd.read() pixbuf = gtkgui_helpers.get_pixbuf_from_data(data) try: # rescale it pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'vcard') except AttributeError: # unknown format dialogs.ErrorDialog(_('Could not load image'), transient_for=self.window) return self.dialog.destroy() self.dialog = None button = self.xml.get_object('PHOTO_button') image = button.get_image() image.set_from_pixbuf(pixbuf) button.show() text_button = self.xml.get_object('NOPHOTO_button') text_button.hide() self.avatar_encoded = base64.b64encode(data).decode('utf-8') # returns None if unknown type self.avatar_mime_type = mimetypes.guess_type(path_to_file)[0] if must_delete: try: os.remove(path_to_file) except OSError: gajim.log.debug('Cannot remove %s' % path_to_file)
def populate(self, contacts): self.create_window() self.create_table() if not contacts or len(contacts) == 0: # Tooltip for merged accounts row accounts = helpers.get_notification_icon_tooltip_dict() self.spacer_label = '' self.fill_table_with_accounts(accounts) self.win.add(self.table) return # primary contact prim_contact = gajim.contacts.get_highest_prio_contact_from_contacts( contacts) puny_jid = helpers.sanitize_filename(prim_contact.jid) table_size = 3 file_ = helpers.get_avatar_path(os.path.join(gajim.AVATAR_PATH, puny_jid)) if file_: with open(file_, 'rb') as file_data: pix = gtkgui_helpers.get_pixbuf_from_data(file_data.read()) pix = gtkgui_helpers.get_scaled_pixbuf(pix, 'tooltip') self.avatar_image.set_from_pixbuf(pix) table_size = 4 else: self.avatar_image.set_from_pixbuf(None) vcard_table = Gtk.Grid() vcard_table.insert_row(0) for i in range(0, table_size): vcard_table.insert_column(0) vcard_table.set_property('column-spacing', 2) vcard_current_row = 1 properties = [] name_markup = '<span weight="bold">' + GLib.markup_escape_text( prim_contact.get_shown_name()) + '</span>' if gajim.config.get('mergeaccounts'): name_markup += " <span foreground='%s'>(%s)</span>" % ( gajim.config.get('tooltip_account_name_color'), GLib.markup_escape_text(prim_contact.account.name)) if self.account and helpers.jid_is_blocked(self.account, prim_contact.jid): name_markup += _(' [blocked]') if self.account and \ self.account in gajim.interface.minimized_controls and \ prim_contact.jid in gajim.interface.minimized_controls[self.account]: name_markup += _(' [minimized]') properties.append((name_markup, None)) num_resources = 0 # put contacts in dict, where key is priority contacts_dict = {} for contact in contacts: if contact.resource: num_resources += 1 if contact.priority in contacts_dict: contacts_dict[int(contact.priority)].append(contact) else: contacts_dict[int(contact.priority)] = [contact] if num_resources > 1: properties.append((_('Status: '), ' ')) transport = gajim.get_transport_name_from_jid(prim_contact.jid) if transport: file_path = os.path.join(helpers.get_transport_path(transport), '16x16') else: iconset = gajim.config.get('iconset') if not iconset: iconset = 'dcraven' file_path = os.path.join(helpers.get_iconset_path(iconset), '16x16') contact_keys = sorted(contacts_dict.keys()) contact_keys.reverse() for priority in contact_keys: for acontact in contacts_dict[priority]: status_line = self.get_status_info(acontact.resource, acontact.priority, acontact.show, acontact.status) icon_name = self._get_icon_name_for_tooltip(acontact) self.add_status_row(file_path, icon_name, status_line, acontact.last_status_time) properties.append((self.table, None)) else: # only one resource if contact.show: show = helpers.get_uf_show(contact.show) if not self.check_last_time and self.account: if contact.show == 'offline': if not contact.last_status_time: gajim.connections[self.account].\ request_last_status_time(contact.jid, '') else: self.check_last_time = contact.last_status_time elif contact.resource: gajim.connections[self.account].\ request_last_status_time( contact.jid, contact.resource) if contact.last_activity_time: self.check_last_time = contact.last_activity_time else: self.check_last_time = None if contact.last_status_time: vcard_current_row += 1 if contact.show == 'offline': text = ' - ' + _('Last status: %s') else: text = _(' since %s') if time.strftime('%j', time.localtime()) == \ time.strftime('%j', contact.last_status_time): # it's today, show only the locale hour representation local_time = time.strftime('%X', contact.last_status_time) else: # time.strftime returns locale encoded string local_time = time.strftime('%c', contact.last_status_time) text = text % local_time show += text if self.account and \ prim_contact.jid in gajim.gc_connected[self.account]: if gajim.gc_connected[self.account][prim_contact.jid]: show = _('Connected') else: show = _('Disconnected') show = self.colorize_status(show) if contact.status: status = contact.status.strip() if status: # reduce long status # (no more than 300 chars on line and no more than # 5 lines) # status is wrapped status = helpers.reduce_chars_newlines(status, 300, 5) # escape markup entities. status = GLib.markup_escape_text(status) properties.append(('<i>%s</i>' % status, None)) properties.append((show, None)) self._append_pep_info(contact, properties) properties.append((_('Jabber ID: '), '\u200E' + "<b>%s</b>" % \ prim_contact.jid)) # contact has only one ressource if num_resources == 1 and contact.resource: properties.append((_('Resource: '), GLib.markup_escape_text( contact.resource) + ' (' + str(contact.priority) + ')')) if self.account and prim_contact.sub and prim_contact.sub != 'both' and\ prim_contact.jid not in gajim.gc_connected[self.account]: # ('both' is the normal sub so we don't show it) properties.append(( _('Subscription: '), GLib.markup_escape_text( helpers.get_uf_sub(prim_contact.sub)))) if prim_contact.keyID: keyID = None if len(prim_contact.keyID) == 8: keyID = prim_contact.keyID elif len(prim_contact.keyID) == 16: keyID = prim_contact.keyID[8:] if keyID: properties.append((_('OpenPGP: '), GLib.markup_escape_text( keyID))) if contact.last_activity_time: last_active = datetime(*contact.last_activity_time[:6]) current = datetime.now() diff = current - last_active diff = timedelta(diff.days, diff.seconds) if last_active.date() == current.date(): formatted = last_active.strftime("%X") else: formatted = last_active.strftime("%c") # Do not show the "Idle since" and "Idle for" items if there # is no meaningful difference between last activity time and # current time. if diff.days > 0 or diff.seconds > 0: cs = "<span foreground='%s'>" % gajim.config.get( 'tooltip_idle_color') cs += '%s</span>' properties.append((str(), None)) idle_since = cs % _("Idle since %s") properties.append((idle_since % formatted, None)) idle_for = cs % _("Idle for %s") properties.append((idle_for % str(diff), None)) while properties: property_ = properties.pop(0) vcard_current_row += 1 label = Gtk.Label() if not properties and table_size == 4: label.set_vexpand(True) label.set_halign(Gtk.Align.START) label.set_valign(Gtk.Align.START) if property_[1]: label.set_markup(property_[0]) vcard_table.attach(label, 1, vcard_current_row, 1, 1) label = Gtk.Label() if not properties and table_size == 4: label.set_vexpand(True) label.set_halign(Gtk.Align.START) label.set_valign(Gtk.Align.START) label.set_markup(property_[1]) label.set_line_wrap(True) vcard_table.attach(label, 2, vcard_current_row, 1, 1) else: if isinstance(property_[0], str): label.set_markup(property_[0]) label.set_line_wrap(True) else: label = property_[0] vcard_table.attach(label, 1, vcard_current_row, 2, 1) self.avatar_image.set_halign(Gtk.Align.START) self.avatar_image.set_valign(Gtk.Align.START) if table_size == 4: vcard_table.attach(self.avatar_image, 3, 2, 1, vcard_current_row - 1) gajim.plugin_manager.gui_extension_point('roster_tooltip_populate', self, contacts, vcard_table) self.win.add(vcard_table)
def populate(self, contact): if not contact: return self.create_window() vcard_table = Gtk.Grid() vcard_table.insert_row(0) vcard_table.insert_row(0) vcard_table.insert_row(0) vcard_table.insert_column(0) vcard_table.set_property('column-spacing', 2) vcard_current_row = 1 properties = [] nick_markup = '<b>' + GLib.markup_escape_text(contact.get_shown_name())\ + '</b>' properties.append((nick_markup, None)) if contact.status: # status message status = contact.status.strip() if status != '': # escape markup entities status = helpers.reduce_chars_newlines(status, 300, 5) status = '<i>' + GLib.markup_escape_text(status) + '</i>' properties.append((status, None)) show = helpers.get_uf_show(contact.show) show = self.colorize_status(show) properties.append((show, None)) if contact.jid.strip(): properties.append((_('Jabber ID: '), '\u200E' + "<b>%s</b>" % \ contact.jid)) if hasattr(contact, 'resource') and contact.resource.strip(): properties.append((_('Resource: '), GLib.markup_escape_text( contact.resource))) if contact.affiliation != 'none': uf_affiliation = helpers.get_uf_affiliation(contact.affiliation) uf_affiliation = \ _('%(owner_or_admin_or_member)s of this group chat') % \ {'owner_or_admin_or_member': uf_affiliation} uf_affiliation = self.colorize_affiliation(uf_affiliation) properties.append((uf_affiliation, None)) # Add avatar puny_name = helpers.sanitize_filename(contact.name) puny_room = helpers.sanitize_filename(contact.room_jid) file_ = helpers.get_avatar_path(os.path.join(gajim.AVATAR_PATH, puny_room, puny_name)) if file_: with open(file_, 'rb') as file_data: pix = gtkgui_helpers.get_pixbuf_from_data(file_data.read()) pix = gtkgui_helpers.get_scaled_pixbuf(pix, 'tooltip') self.avatar_image.set_from_pixbuf(pix) else: self.avatar_image.set_from_pixbuf(None) while properties: property_ = properties.pop(0) vcard_current_row += 1 label = Gtk.Label() if not properties: label.set_vexpand(True) label.set_halign(Gtk.Align.START) label.set_valign(Gtk.Align.START) if property_[1]: label.set_markup(property_[0]) vcard_table.attach(label, 1, vcard_current_row, 1, 1) label = Gtk.Label() if not properties: label.set_vexpand(True) label.set_halign(Gtk.Align.START) label.set_valign(Gtk.Align.START) label.set_markup(property_[1]) label.set_line_wrap(True) vcard_table.attach(label, 2, vcard_current_row, 1, 1) else: label.set_markup(property_[0]) label.set_line_wrap(True) vcard_table.attach(label, 1, vcard_current_row, 2, 1) self.avatar_image.set_halign(Gtk.Align.START) self.avatar_image.set_valign(Gtk.Align.START) vcard_table.attach(self.avatar_image, 3, 2, 1, vcard_current_row - 1) gajim.plugin_manager.gui_extension_point('gc_tooltip_populate', self, contact, vcard_table) self.win.add(vcard_table)
def populate(self, contacts): self.create_window() self.create_table() if not contacts or len(contacts) == 0: # Tooltip for merged accounts row accounts = helpers.get_notification_icon_tooltip_dict() self.spacer_label = '' self.fill_table_with_accounts(accounts) self.win.add(self.table) return # primary contact prim_contact = gajim.contacts.get_highest_prio_contact_from_contacts( contacts) puny_jid = helpers.sanitize_filename(prim_contact.jid) table_size = 3 file_ = helpers.get_avatar_path(os.path.join(gajim.AVATAR_PATH, puny_jid)) if file_: with open(file_, 'rb') as file_data: pix = gtkgui_helpers.get_pixbuf_from_data(file_data.read()) pix = gtkgui_helpers.get_scaled_pixbuf(pix, 'tooltip') self.avatar_image.set_from_pixbuf(pix) table_size = 4 else: self.avatar_image.set_from_pixbuf(None) vcard_table = Gtk.Grid() vcard_table.insert_row(0) for i in range(0, table_size): vcard_table.insert_column(0) vcard_table.set_property('column-spacing', 2) vcard_current_row = 1 properties = [] name_markup = '<span weight="bold">' + GLib.markup_escape_text( prim_contact.get_shown_name()) + '</span>' if gajim.config.get('mergeaccounts'): name_markup += " <span foreground='%s'>(%s)</span>" % ( gajim.config.get('tooltip_account_name_color'), GLib.markup_escape_text(prim_contact.account.name)) if self.account and helpers.jid_is_blocked(self.account, prim_contact.jid): name_markup += _(' [blocked]') if self.account and \ self.account in gajim.interface.minimized_controls and \ prim_contact.jid in gajim.interface.minimized_controls[self.account]: name_markup += _(' [minimized]') properties.append((name_markup, None)) num_resources = 0 # put contacts in dict, where key is priority contacts_dict = {} for contact in contacts: if contact.resource: num_resources += 1 if contact.priority in contacts_dict: contacts_dict[int(contact.priority)].append(contact) else: contacts_dict[int(contact.priority)] = [contact] if num_resources > 1: properties.append((_('Status: '), ' ')) transport = gajim.get_transport_name_from_jid(prim_contact.jid) if transport: file_path = os.path.join(helpers.get_transport_path(transport), '16x16') else: iconset = gajim.config.get('iconset') if not iconset: iconset = 'dcraven' file_path = os.path.join(helpers.get_iconset_path(iconset), '16x16') contact_keys = sorted(contacts_dict.keys()) contact_keys.reverse() for priority in contact_keys: for acontact in contacts_dict[priority]: status_line = self.get_status_info(acontact.resource, acontact.priority, acontact.show, acontact.status) icon_name = self._get_icon_name_for_tooltip(acontact) self.add_status_row(file_path, icon_name, status_line, acontact.last_status_time) properties.append((self.table, None)) else: # only one resource if contact.show: show = helpers.get_uf_show(contact.show) if not self.check_last_time and self.account: if contact.show == 'offline': if not contact.last_status_time: gajim.connections[self.account].\ request_last_status_time(contact.jid, '') else: self.check_last_time = contact.last_status_time elif contact.resource: gajim.connections[self.account].\ request_last_status_time( contact.jid, contact.resource) if contact.last_activity_time: self.check_last_time = contact.last_activity_time else: self.check_last_time = None if contact.last_status_time: vcard_current_row += 1 if contact.show == 'offline': text = ' - ' + _('Last status: %s') else: text = _(' since %s') if time.strftime('%j', time.localtime()) == \ time.strftime('%j', contact.last_status_time): # it's today, show only the locale hour representation local_time = time.strftime('%X', contact.last_status_time) else: # time.strftime returns locale encoded string local_time = time.strftime('%c', contact.last_status_time) text = text % local_time show += text if self.account and \ prim_contact.jid in gajim.gc_connected[self.account]: if gajim.gc_connected[self.account][prim_contact.jid]: show = _('Connected') else: show = _('Disconnected') show = self.colorize_status(show) if contact.status: status = contact.status.strip() if status: # reduce long status # (no more than 300 chars on line and no more than # 5 lines) # status is wrapped status = helpers.reduce_chars_newlines(status, 300, 5) # escape markup entities. status = GLib.markup_escape_text(status) properties.append(('<i>%s</i>' % status, None)) properties.append((show, None)) self._append_pep_info(contact, properties) properties.append((_('Jabber ID: '), '\u200E' + "<b>%s</b>" % \ prim_contact.jid)) # contact has only one ressource if num_resources == 1 and contact.resource: properties.append((_('Resource: '), GLib.markup_escape_text( contact.resource) + ' (' + str(contact.priority) + ')')) if self.account and prim_contact.sub and prim_contact.sub != 'both' and\ prim_contact.jid not in gajim.gc_connected[self.account]: # ('both' is the normal sub so we don't show it) properties.append(( _('Subscription: '), GLib.markup_escape_text( helpers.get_uf_sub(prim_contact.sub)))) if prim_contact.keyID: keyID = None if len(prim_contact.keyID) == 8: keyID = prim_contact.keyID elif len(prim_contact.keyID) == 16: keyID = prim_contact.keyID[8:] if keyID: properties.append((_('OpenPGP: '), GLib.markup_escape_text( keyID))) if contact.last_activity_time: last_active = datetime(*contact.last_activity_time[:6]) current = datetime.now() diff = current - last_active diff = timedelta(diff.days, diff.seconds) if last_active.date() == current.date(): formatted = last_active.strftime("%X") else: formatted = last_active.strftime("%c") # Do not show the "Idle since" and "Idle for" items if there # is no meaningful difference between last activity time and # current time. if diff.days > 0 or diff.seconds > 0: cs = "<span foreground='%s'>" % gajim.config.get( 'tooltip_idle_color') cs += '%s</span>' properties.append((str(), None)) idle_since = cs % _("Idle since %s") properties.append((idle_since % formatted, None)) idle_for = cs % _("Idle for %s") properties.append((idle_for % str(diff), None)) while properties: property_ = properties.pop(0) vcard_current_row += 1 label = Gtk.Label() if not properties and table_size == 4: label.set_vexpand(True) label.set_alignment(0, 0) if property_[1]: label.set_markup(property_[0]) vcard_table.attach(label, 1, vcard_current_row, 1, 1) label = Gtk.Label() if not properties and table_size == 4: label.set_vexpand(True) label.set_alignment(0, 0) label.set_markup(property_[1]) label.set_line_wrap(True) vcard_table.attach(label, 2, vcard_current_row, 1, 1) else: if isinstance(property_[0], str): label.set_markup(property_[0]) label.set_line_wrap(True) else: label = property_[0] vcard_table.attach(label, 1, vcard_current_row, 2, 1) self.avatar_image.set_alignment(0, 0) if table_size == 4: vcard_table.attach(self.avatar_image, 3, 2, 1, vcard_current_row - 1) gajim.plugin_manager.gui_extension_point('roster_tooltip_populate', self, contacts, vcard_table) self.win.add(vcard_table)
def populate(self, contact): if not contact: return self.create_window() vcard_table = Gtk.Grid() vcard_table.insert_row(0) vcard_table.insert_row(0) vcard_table.insert_row(0) vcard_table.insert_column(0) vcard_table.set_property('column-spacing', 2) vcard_current_row = 1 properties = [] nick_markup = '<b>' + GLib.markup_escape_text(contact.get_shown_name())\ + '</b>' properties.append((nick_markup, None)) if contact.status: # status message status = contact.status.strip() if status != '': # escape markup entities status = helpers.reduce_chars_newlines(status, 300, 5) status = '<i>' + GLib.markup_escape_text(status) + '</i>' properties.append((status, None)) show = helpers.get_uf_show(contact.show) show = self.colorize_status(show) properties.append((show, None)) if contact.jid.strip(): properties.append((_('Jabber ID: '), '\u200E' + "<b>%s</b>" % \ contact.jid)) if hasattr(contact, 'resource') and contact.resource.strip(): properties.append((_('Resource: '), GLib.markup_escape_text( contact.resource))) if contact.affiliation != 'none': uf_affiliation = helpers.get_uf_affiliation(contact.affiliation) uf_affiliation = \ _('%(owner_or_admin_or_member)s of this group chat') % \ {'owner_or_admin_or_member': uf_affiliation} uf_affiliation = self.colorize_affiliation(uf_affiliation) properties.append((uf_affiliation, None)) # Add avatar puny_name = helpers.sanitize_filename(contact.name) puny_room = helpers.sanitize_filename(contact.room_jid) file_ = helpers.get_avatar_path(os.path.join(gajim.AVATAR_PATH, puny_room, puny_name)) if file_: with open(file_, 'rb') as file_data: pix = gtkgui_helpers.get_pixbuf_from_data(file_data.read()) pix = gtkgui_helpers.get_scaled_pixbuf(pix, 'tooltip') self.avatar_image.set_from_pixbuf(pix) else: self.avatar_image.set_from_pixbuf(None) while properties: property_ = properties.pop(0) vcard_current_row += 1 label = Gtk.Label() if not properties: label.set_vexpand(True) label.set_alignment(0, 0) if property_[1]: label.set_markup(property_[0]) vcard_table.attach(label, 1, vcard_current_row, 1, 1) label = Gtk.Label() if not properties: label.set_vexpand(True) label.set_alignment(0, 0) label.set_markup(property_[1]) label.set_line_wrap(True) vcard_table.attach(label, 2, vcard_current_row, 1, 1) else: label.set_markup(property_[0]) label.set_line_wrap(True) vcard_table.attach(label, 1, vcard_current_row, 2, 1) self.avatar_image.set_alignment(0, 0) vcard_table.attach(self.avatar_image, 3, 2, 1, vcard_current_row - 1) gajim.plugin_manager.gui_extension_point('gc_tooltip_populate', self, contact, vcard_table) self.win.add(vcard_table)
def populate(self, contacts, account, typ): """ Populate the Tooltip Grid with data of from the contact """ self.current_row = 0 self.account = account if self.last_widget: self.last_widget.set_vexpand(False) self.clear_tooltip() if account == 'all': # Tooltip for merged accounts row accounts = helpers.get_notification_icon_tooltip_dict() self.spacer_label = '' self.fill_table_with_accounts(accounts) self.tooltip_grid.attach(self.table, 0, 3, 2, 1) self.table.show_all() return if typ == 'account': jid = gajim.get_jid_from_account(account) contacts = [] connection = gajim.connections[account] # get our current contact info nbr_on, nbr_total = gajim.\ contacts.get_nb_online_total_contacts( accounts=[account]) account_name = account if gajim.account_is_connected(account): account_name += ' (%s/%s)' % (repr(nbr_on), repr(nbr_total)) contact = gajim.contacts.create_self_contact(jid=jid, account=account, name=account_name, show=connection.get_status(), status=connection.status, resource=connection.server_resource, priority=connection.priority) if gajim.connections[account].gpg: contact.keyID = gajim.config.get_per('accounts', connection.name, 'keyid') contacts.append(contact) # if we're online ... if connection.connection: roster = connection.connection.getRoster() # in threadless connection when no roster stanza is sent # 'roster' is None if roster and roster.getItem(jid): resources = roster.getResources(jid) # ...get the contact info for our other online # resources for resource in resources: # Check if we already have this resource found = False for contact_ in contacts: if contact_.resource == resource: found = True break if found: continue show = roster.getShow(jid + '/' + resource) if not show: show = 'online' contact = gajim.contacts.create_self_contact( jid=jid, account=account, show=show, status=roster.getStatus( jid + '/' + resource), priority=roster.getPriority( jid + '/' + resource), resource=resource) contacts.append(contact) # Username/Account/Groupchat self.prim_contact = gajim.contacts.get_highest_prio_contact_from_contacts( contacts) self.contact_jid = self.prim_contact.jid name = GLib.markup_escape_text(self.prim_contact.get_shown_name()) name_markup = '<b>{}</b>'.format(name) if gajim.config.get('mergeaccounts'): color = gajim.config.get('tooltip_account_name_color') account_name = GLib.markup_escape_text(self.prim_contact.account.name) name_markup += " <span foreground='{}'>({})</span>".format( color, account_name) if account and helpers.jid_is_blocked(account, self.prim_contact.jid): name_markup += _(' [blocked]') try: if self.prim_contact.jid in gajim.interface.minimized_controls[account]: name_markup += _(' [minimized]') except KeyError: pass self.name.set_markup(name_markup) self.name.show() self.num_resources = 0 # put contacts in dict, where key is priority contacts_dict = {} for contact in contacts: if contact.resource: self.num_resources += 1 priority = int(contact.priority) if priority in contacts_dict: contacts_dict[priority].append(contact) else: contacts_dict[priority] = [contact] if self.num_resources > 1: self.status_label.show() transport = gajim.get_transport_name_from_jid(self.prim_contact.jid) if transport: file_path = os.path.join(helpers.get_transport_path(transport), '16x16') else: iconset = gajim.config.get('iconset') if not iconset: iconset = 'dcraven' file_path = os.path.join(helpers.get_iconset_path(iconset), '16x16') contact_keys = sorted(contacts_dict.keys()) contact_keys.reverse() for priority in contact_keys: for acontact in contacts_dict[priority]: icon_name = self._get_icon_name_for_tooltip(acontact) if acontact.status and len(acontact.status) > 25: status = '' add_text = True else: status = acontact.status add_text = False status_line = self.get_status_info(acontact.resource, acontact.priority, acontact.show, status) self.add_status_row(file_path, icon_name, status_line, acontact.last_status_time) if add_text: self.add_text_row(acontact.status, 2) self.tooltip_grid.attach(self.table, 0, 3, 2, 1) self.table.show_all() else: # only one resource if contact.show: request_time = False try: last_time = self.check_last_time[contact] if isinstance(last_time, float) and last_time < time.time() - 60: request_time = True except KeyError: request_time = True if request_time: if contact.show == 'offline': gajim.connections[account].\ request_last_status_time(contact.jid, '') elif contact.resource: gajim.connections[account].\ request_last_status_time( contact.jid, contact.resource) self.check_last_time[contact] = time.time() if contact.status: status = contact.status.strip() if status: self.status.set_text(status) self.status.show() self.status_label.show() # PEP Info self._append_pep_info(contact) # JID self.jid.set_text(self.prim_contact.jid) self.jid.show() self.jid_label.show() # contact has only one ressource if self.num_resources == 1 and contact.resource: res = GLib.markup_escape_text(contact.resource) prio = str(contact.priority) self.resource.set_text("{} ({})".format(res, prio)) self.resource.show() self.resource_label.show() if self.prim_contact.jid not in gajim.gc_connected[account]: if (account and self.prim_contact.sub and self.prim_contact.sub != 'both'): # ('both' is the normal sub so we don't show it) self.sub.set_text(helpers.get_uf_sub(self.prim_contact.sub)) self.sub.show() self.sub_label.show() if self.prim_contact.keyID: keyID = None if len(self.prim_contact.keyID) == 8: keyID = self.prim_contact.keyID elif len(self.prim_contact.keyID) == 16: keyID = self.prim_contact.keyID[8:] if keyID: self.pgp.set_text(keyID) self.pgp.show() self.pgp_label.show() self._set_idle_time(contact) # Avatar puny_jid = helpers.sanitize_filename(self.prim_contact.jid) file_ = helpers.get_avatar_path(os.path.join(gajim.AVATAR_PATH, puny_jid)) if file_: with open(file_, 'rb') as file_data: pix = gtkgui_helpers.get_pixbuf_from_data(file_data.read()) pix = gtkgui_helpers.get_scaled_pixbuf(pix, 'tooltip') self.avatar.set_from_pixbuf(pix) self.avatar.show() # Sets the Widget that is at the bottom to expand. # This is needed in case the Picture takes more Space then the Labels i = 1 while i < 15: if self.tooltip_grid.get_child_at(0, i): if self.tooltip_grid.get_child_at(0, i).get_visible(): self.last_widget = self.tooltip_grid.get_child_at(0, i) i += 1 self.last_widget.set_vexpand(True)