Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
	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.table.resize(2, 1)
			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:
			self.avatar_image.set_from_file(file)
			pix = self.avatar_image.get_pixbuf()
			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.Table(table_size, 1)
		vcard_table.set_property('column-spacing', 2)
		vcard_table.set_homogeneous(False)
		vcard_current_row = 1
		properties = []

		name_markup = u'<span weight="bold">' + \
			gobject.markup_escape_text(prim_contact.get_shown_name())\
			+ '</span>'
		if self.account and prim_contact.jid in gajim.connections[
		self.account].blocked_contacts:
			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[contact.priority].append(contact)
				else:
					contacts_dict[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 contact in contacts_dict[priority]:
					status_line = self.get_status_info(contact.resource,
						contact.priority, contact.show, contact.status)
					
					icon_name = self._get_icon_name_for_tooltip(contact)
					self.add_status_row(file_path, icon_name, status_line,
						contact.last_status_time)
			properties.append((self.table,	None))

		else: # only one resource
			if contact.show:
				show = helpers.get_uf_show(contact.show) 
				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)
					local_time = local_time.decode(
						locale.getpreferredencoding())
					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 = '<i>' + show + '</i>'
				# we append show below
				
				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 = gobject.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: '), prim_contact.jid ))

		# contact has only one ressource
		if num_resources == 1 and contact.resource:
			properties.append((_('Resource: '),
				gobject.markup_escape_text(contact.resource) +\
				' (' + unicode(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: '), 
				gobject.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: '),
					gobject.markup_escape_text(keyID)))
		
		while properties:
			property = properties.pop(0)
			vcard_current_row += 1
			vertical_fill = gtk.FILL
			if not properties and table_size == 4:
				vertical_fill |= gtk.EXPAND
			label = gtk.Label()
			label.set_alignment(0, 0)
			if property[1]:
				label.set_markup(property[0])
				vcard_table.attach(label, 1, 2, vcard_current_row,
					vcard_current_row + 1, gtk.FILL, vertical_fill, 0, 0)
				label = gtk.Label()
				label.set_alignment(0, 0)
				label.set_markup(property[1])
				label.set_line_wrap(True)
				vcard_table.attach(label, 2, 3, vcard_current_row,
					vcard_current_row + 1, gtk.EXPAND | gtk.FILL,
						vertical_fill, 0, 0)
			else:
				if isinstance(property[0], (unicode, str)): #FIXME: rm unicode?
					label.set_markup(property[0]) 
					label.set_line_wrap(True)
				else:
					label = property[0]
				vcard_table.attach(label, 1, 3, vcard_current_row,
					vcard_current_row + 1, gtk.FILL, vertical_fill, 0)
		self.avatar_image.set_alignment(0, 0)
		if table_size == 4:
			vcard_table.attach(self.avatar_image, 3, 4, 2,
				vcard_current_row + 1, gtk.FILL, gtk.FILL | gtk.EXPAND, 3, 3)
		self.win.add(vcard_table)
Ejemplo n.º 3
0
def notify(event, jid, account, parameters, advanced_notif_num=None):
	'''Check what type of notifications we want, depending on basic
	and the advanced configuration of notifications and do these notifications;
	advanced_notif_num holds the number of the first (top most) advanced
	notification'''
	# First, find what notifications we want
	do_popup = False
	do_sound = False
	do_cmd = False
	if event == 'status_change':
		new_show = parameters[0]
		status_message = parameters[1]
		# Default: No popup for status change
	elif event == 'contact_connected':
		status_message = parameters
		j = gajim.get_jid_without_resource(jid)
		server = gajim.get_server_from_jid(j)
		account_server = account + '/' + server
		block_transport = False
		if account_server in gajim.block_signed_in_notifications and \
		gajim.block_signed_in_notifications[account_server]:
			block_transport = True
		if helpers.allow_showing_notification(account, 'notify_on_signin') and \
		not gajim.block_signed_in_notifications[account] and not block_transport:
			do_popup = True
		if gajim.config.get_per('soundevents', 'contact_connected',
		'enabled') and not gajim.block_signed_in_notifications[account] and \
		not block_transport:
			do_sound = True
	elif event == 'contact_disconnected':
		status_message = parameters
		if helpers.allow_showing_notification(account, 'notify_on_signout'):
			do_popup = True
		if gajim.config.get_per('soundevents', 'contact_disconnected',
			'enabled'):
			do_sound = True
	elif event == 'new_message':
		message_type = parameters[0]
		is_first_message = parameters[1]
		nickname = parameters[2]
		if gajim.config.get('notification_preview_message'):
			message = parameters[3]
			if message.startswith('/me ') or message.startswith('/me\n'):
				message = '* ' + nickname + message[3:]
		else:
			# We don't want message preview, do_preview = False
			message = ''
		focused = parameters[4]
		if helpers.allow_showing_notification(account, 'notify_on_new_message',
		advanced_notif_num, is_first_message):
			do_popup = True
		if is_first_message and helpers.allow_sound_notification(
		'first_message_received', advanced_notif_num):
			do_sound = True
		elif not is_first_message and focused and \
		helpers.allow_sound_notification('next_message_received_focused',
		advanced_notif_num):
			do_sound = True
		elif not is_first_message and not focused and \
		helpers.allow_sound_notification('next_message_received_unfocused',
		advanced_notif_num):
			do_sound = True
	else:
		print '*Event not implemeted yet*'

	if advanced_notif_num is not None and gajim.config.get_per('notifications',
	str(advanced_notif_num), 'run_command'):
		do_cmd = True

	# Do the wanted notifications
	if do_popup:
		if event in ('contact_connected', 'contact_disconnected',
		'status_change'): # Common code for popup for these three events
			if event == 'contact_disconnected':
				show_image = 'offline.png'
				suffix = '_notif_size_bw'
			else: #Status Change or Connected
				# FIXME: for status change,
				# we don't always 'online.png', but we
				# first need 48x48 for all status
				show_image = 'online.png'
				suffix = '_notif_size_colored'
			transport_name = gajim.get_transport_name_from_jid(jid)
			img = None
			if transport_name:
				img = os.path.join(helpers.get_transport_path(transport_name),
					'48x48', show_image)
			if not img or not os.path.isfile(img):
				iconset = gajim.config.get('iconset')
				img = os.path.join(helpers.get_iconset_path(iconset), '48x48',
					show_image)
			path = gtkgui_helpers.get_path_to_generic_or_avatar(img,
				jid = jid, suffix = suffix)
			if event == 'status_change':
				title = _('%(nick)s Changed Status') % \
					{'nick': gajim.get_name_from_jid(account, jid)}
				text = _('%(nick)s is now %(status)s') % \
					{'nick': gajim.get_name_from_jid(account, jid),\
					'status': helpers.get_uf_show(gajim.SHOW_LIST[new_show])}
				if status_message:
					text = text + " : " + status_message
				popup(_('Contact Changed Status'), jid, account,
					path_to_image=path, title=title, text=text)
			elif event == 'contact_connected':
				title = _('%(nickname)s Signed In') % \
					{'nickname': gajim.get_name_from_jid(account, jid)}
				text = ''
				if status_message:
					text = status_message
				popup(_('Contact Signed In'), jid, account,
					path_to_image=path, title=title, text=text)
			elif event == 'contact_disconnected':
				title = _('%(nickname)s Signed Out') % \
					{'nickname': gajim.get_name_from_jid(account, jid)}
				text = ''
				if status_message:
					text = status_message
				popup(_('Contact Signed Out'), jid, account,
					path_to_image=path, title=title, text=text)
		elif event == 'new_message':
			if message_type == 'normal': # single message
				event_type = _('New Single Message')
				img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
					'single_msg_recv.png')
				title = _('New Single Message from %(nickname)s') % \
					{'nickname': nickname}
				text = message
			elif message_type == 'pm': # private message
				event_type = _('New Private Message')
				room_name = gajim.get_nick_from_jid(jid)
				img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
					'priv_msg_recv.png')
				title = _('New Private Message from group chat %s') % room_name
				if message:
					text = _('%(nickname)s: %(message)s') % {'nickname': nickname,
						'message': message}
				else:
					text = _('Messaged by %(nickname)s') % {'nickname': nickname}

			else: # chat message
				event_type = _('New Message')
				img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
					'chat_msg_recv.png')
				title = _('New Message from %(nickname)s') % \
					{'nickname': nickname}
				text = message
			path = gtkgui_helpers.get_path_to_generic_or_avatar(img)
			popup(event_type, jid, account, message_type,
				path_to_image=path, title=title, text=text)

	if do_sound:
		snd_file = None
		snd_event = None # If not snd_file, play the event
		if event == 'new_message':
			if advanced_notif_num is not None and gajim.config.get_per(
			'notifications', str(advanced_notif_num), 'sound') == 'yes':
				snd_file = gajim.config.get_per('notifications',
					str(advanced_notif_num), 'sound_file')
			elif advanced_notif_num is not None and gajim.config.get_per(
			'notifications', str(advanced_notif_num), 'sound') == 'no':
				pass # do not set snd_event
			elif is_first_message:
				snd_event = 'first_message_received'
			elif focused:
				snd_event = 'next_message_received_focused'
			else:
				snd_event = 'next_message_received_unfocused'
		elif event in ('contact_connected', 'contact_disconnected'):
			snd_event = event
		if snd_file:
			helpers.play_sound_file(snd_file)
		if snd_event:
			helpers.play_sound(snd_event)

	if do_cmd:
		command = gajim.config.get_per('notifications', str(advanced_notif_num),
			'command')
		try:
			helpers.exec_command(command)
		except Exception:
			pass
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
def notify(event, jid, account, parameters, advanced_notif_num=None):
    '''Check what type of notifications we want, depending on basic
	and the advanced configuration of notifications and do these notifications;
	advanced_notif_num holds the number of the first (top most) advanced
	notification'''
    # First, find what notifications we want
    do_popup = False
    do_sound = False
    do_cmd = False
    if event == 'status_change':
        new_show = parameters[0]
        status_message = parameters[1]
        # Default: No popup for status change
    elif event == 'contact_connected':
        status_message = parameters
        j = gajim.get_jid_without_resource(jid)
        server = gajim.get_server_from_jid(j)
        account_server = account + '/' + server
        block_transport = False
        if account_server in gajim.block_signed_in_notifications and \
        gajim.block_signed_in_notifications[account_server]:
            block_transport = True
        if helpers.allow_showing_notification(account, 'notify_on_signin') and \
        not gajim.block_signed_in_notifications[account] and not block_transport:
            do_popup = True
        if gajim.config.get_per('soundevents', 'contact_connected',
        'enabled') and not gajim.block_signed_in_notifications[account] and \
        not block_transport:
            do_sound = True
    elif event == 'contact_disconnected':
        status_message = parameters
        if helpers.allow_showing_notification(account, 'notify_on_signout'):
            do_popup = True
        if gajim.config.get_per('soundevents', 'contact_disconnected',
                                'enabled'):
            do_sound = True
    elif event == 'new_message':
        message_type = parameters[0]
        is_first_message = parameters[1]
        nickname = parameters[2]
        if gajim.config.get('notification_preview_message'):
            message = parameters[3]
            if message.startswith('/me ') or message.startswith('/me\n'):
                message = '* ' + nickname + message[3:]
        else:
            # We don't want message preview, do_preview = False
            message = ''
        focused = parameters[4]
        if helpers.allow_showing_notification(account, 'notify_on_new_message',
                                              advanced_notif_num,
                                              is_first_message):
            do_popup = True
        if is_first_message and helpers.allow_sound_notification(
                'first_message_received', advanced_notif_num):
            do_sound = True
        elif not is_first_message and focused and \
        helpers.allow_sound_notification('next_message_received_focused',
        advanced_notif_num):
            do_sound = True
        elif not is_first_message and not focused and \
        helpers.allow_sound_notification('next_message_received_unfocused',
        advanced_notif_num):
            do_sound = True
    else:
        print '*Event not implemeted yet*'

    if advanced_notif_num is not None and gajim.config.get_per(
            'notifications', str(advanced_notif_num), 'run_command'):
        do_cmd = True

    # Do the wanted notifications
    if do_popup:
        if event in ('contact_connected', 'contact_disconnected',
                     'status_change'
                     ):  # Common code for popup for these three events
            if event == 'contact_disconnected':
                show_image = 'offline.png'
                suffix = '_notif_size_bw'
            else:  #Status Change or Connected
                # FIXME: for status change,
                # we don't always 'online.png', but we
                # first need 48x48 for all status
                show_image = 'online.png'
                suffix = '_notif_size_colored'
            transport_name = gajim.get_transport_name_from_jid(jid)
            img = None
            if transport_name:
                img = os.path.join(helpers.get_transport_path(transport_name),
                                   '48x48', show_image)
            if not img or not os.path.isfile(img):
                iconset = gajim.config.get('iconset')
                img = os.path.join(helpers.get_iconset_path(iconset), '48x48',
                                   show_image)
            path = gtkgui_helpers.get_path_to_generic_or_avatar(img,
                                                                jid=jid,
                                                                suffix=suffix)
            if event == 'status_change':
                title = _('%(nick)s Changed Status') % \
                 {'nick': gajim.get_name_from_jid(account, jid)}
                text = _('%(nick)s is now %(status)s') % \
                 {'nick': gajim.get_name_from_jid(account, jid),\
                 'status': helpers.get_uf_show(gajim.SHOW_LIST[new_show])}
                if status_message:
                    text = text + " : " + status_message
                popup(_('Contact Changed Status'),
                      jid,
                      account,
                      path_to_image=path,
                      title=title,
                      text=text)
            elif event == 'contact_connected':
                title = _('%(nickname)s Signed In') % \
                 {'nickname': gajim.get_name_from_jid(account, jid)}
                text = ''
                if status_message:
                    text = status_message
                popup(_('Contact Signed In'),
                      jid,
                      account,
                      path_to_image=path,
                      title=title,
                      text=text)
            elif event == 'contact_disconnected':
                title = _('%(nickname)s Signed Out') % \
                 {'nickname': gajim.get_name_from_jid(account, jid)}
                text = ''
                if status_message:
                    text = status_message
                popup(_('Contact Signed Out'),
                      jid,
                      account,
                      path_to_image=path,
                      title=title,
                      text=text)
        elif event == 'new_message':
            if message_type == 'normal':  # single message
                event_type = _('New Single Message')
                img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
                                   'single_msg_recv.png')
                title = _('New Single Message from %(nickname)s') % \
                 {'nickname': nickname}
                text = message
            elif message_type == 'pm':  # private message
                event_type = _('New Private Message')
                room_name = gajim.get_nick_from_jid(jid)
                img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
                                   'priv_msg_recv.png')
                title = _('New Private Message from group chat %s') % room_name
                if message:
                    text = _('%(nickname)s: %(message)s') % {
                        'nickname': nickname,
                        'message': message
                    }
                else:
                    text = _('Messaged by %(nickname)s') % {
                        'nickname': nickname
                    }

            else:  # chat message
                event_type = _('New Message')
                img = os.path.join(gajim.DATA_DIR, 'pixmaps', 'events',
                                   'chat_msg_recv.png')
                title = _('New Message from %(nickname)s') % \
                 {'nickname': nickname}
                text = message
            path = gtkgui_helpers.get_path_to_generic_or_avatar(img)
            popup(event_type,
                  jid,
                  account,
                  message_type,
                  path_to_image=path,
                  title=title,
                  text=text)

    if do_sound:
        snd_file = None
        snd_event = None  # If not snd_file, play the event
        if event == 'new_message':
            if advanced_notif_num is not None and gajim.config.get_per(
                    'notifications', str(advanced_notif_num),
                    'sound') == 'yes':
                snd_file = gajim.config.get_per('notifications',
                                                str(advanced_notif_num),
                                                'sound_file')
            elif advanced_notif_num is not None and gajim.config.get_per(
                    'notifications', str(advanced_notif_num), 'sound') == 'no':
                pass  # do not set snd_event
            elif is_first_message:
                snd_event = 'first_message_received'
            elif focused:
                snd_event = 'next_message_received_focused'
            else:
                snd_event = 'next_message_received_unfocused'
        elif event in ('contact_connected', 'contact_disconnected'):
            snd_event = event
        if snd_file:
            helpers.play_sound_file(snd_file)
        if snd_event:
            helpers.play_sound(snd_event)

    if do_cmd:
        command = gajim.config.get_per('notifications',
                                       str(advanced_notif_num), 'command')
        try:
            helpers.exec_command(command)
        except Exception:
            pass
Ejemplo n.º 7
0
    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.table.resize(2, 1)
            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:
            self.avatar_image.set_from_file(file)
            pix = self.avatar_image.get_pixbuf()
            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.Table(table_size, 1)
        vcard_table.set_property('column-spacing', 2)
        vcard_table.set_homogeneous(False)
        vcard_current_row = 1
        properties = []

        name_markup = u'<span weight="bold">' + \
         gobject.markup_escape_text(prim_contact.get_shown_name())\
         + '</span>'
        if self.account and prim_contact.jid in gajim.connections[
                self.account].blocked_contacts:
            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[contact.priority].append(contact)
                else:
                    contacts_dict[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 contact in contacts_dict[priority]:
                    status_line = self.get_status_info(contact.resource,
                                                       contact.priority,
                                                       contact.show,
                                                       contact.status)

                    icon_name = self._get_icon_name_for_tooltip(contact)
                    self.add_status_row(file_path, icon_name, status_line,
                                        contact.last_status_time)
            properties.append((self.table, None))

        else:  # only one resource
            if contact.show:
                show = helpers.get_uf_show(contact.show)
                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)
                    local_time = local_time.decode(
                        locale.getpreferredencoding())
                    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 = '<i>' + show + '</i>'
                # we append show below

                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 = gobject.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: '), prim_contact.jid))

        # contact has only one ressource
        if num_resources == 1 and contact.resource:
            properties.append((_('Resource: '),
             gobject.markup_escape_text(contact.resource) +\
             ' (' + unicode(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: '),
                               gobject.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: '), gobject.markup_escape_text(keyID)))

        while properties:
            property = properties.pop(0)
            vcard_current_row += 1
            vertical_fill = gtk.FILL
            if not properties and table_size == 4:
                vertical_fill |= gtk.EXPAND
            label = gtk.Label()
            label.set_alignment(0, 0)
            if property[1]:
                label.set_markup(property[0])
                vcard_table.attach(label, 1, 2, vcard_current_row,
                                   vcard_current_row + 1, gtk.FILL,
                                   vertical_fill, 0, 0)
                label = gtk.Label()
                label.set_alignment(0, 0)
                label.set_markup(property[1])
                label.set_line_wrap(True)
                vcard_table.attach(label, 2, 3, vcard_current_row,
                                   vcard_current_row + 1,
                                   gtk.EXPAND | gtk.FILL, vertical_fill, 0, 0)
            else:
                if isinstance(property[0],
                              (unicode, str)):  #FIXME: rm unicode?
                    label.set_markup(property[0])
                    label.set_line_wrap(True)
                else:
                    label = property[0]
                vcard_table.attach(label, 1, 3, vcard_current_row,
                                   vcard_current_row + 1, gtk.FILL,
                                   vertical_fill, 0)
        self.avatar_image.set_alignment(0, 0)
        if table_size == 4:
            vcard_table.attach(self.avatar_image, 3, 4, 2,
                               vcard_current_row + 1, gtk.FILL,
                               gtk.FILL | gtk.EXPAND, 3, 3)
        self.win.add(vcard_table)