def fill_status_label(self): if self.xml.get_object('information_notebook').get_n_pages() < 2: return contact_list = gajim.contacts.get_contacts(self.account, self.contact.jid) # stats holds show and status message stats = '' one = True # Are we adding the first line ? if contact_list: for c in contact_list: if not one: stats += '\n' stats += helpers.get_uf_show(c.show) if c.status: stats += ': ' + c.status if c.last_status_time: stats += '\n' + _('since %s') % time.strftime('%c', c.last_status_time).decode(locale.getpreferredencoding()) one = False else: # Maybe gc_vcard ? stats = helpers.get_uf_show(self.contact.show) if self.contact.status: stats += ': ' + self.contact.status status_label = self.xml.get_object('status_label') status_label.set_max_width_chars(15) status_label.set_text(stats) status_label_eventbox = self.xml.get_object('status_label_eventbox') status_label_eventbox.set_tooltip_text(stats)
def fill_status_label(self): if self.xml.get_object('information_notebook').get_n_pages() < 2: return contact_list = gajim.contacts.get_contacts(self.account, self.contact.jid) # stats holds show and status message stats = '' one = True # Are we adding the first line ? if contact_list: for c in contact_list: if not one: stats += '\n' stats += helpers.get_uf_show(c.show) if c.status: stats += ': ' + c.status if c.last_status_time: stats += '\n' + _('since %s') % time.strftime( '%c', c.last_status_time).decode( locale.getpreferredencoding()) one = False else: # Maybe gc_vcard ? stats = helpers.get_uf_show(self.contact.show) if self.contact.status: stats += ': ' + self.contact.status status_label = self.xml.get_object('status_label') status_label.set_max_width_chars(15) status_label.set_text(stats) status_label_eventbox = self.xml.get_object('status_label_eventbox') status_label_eventbox.set_tooltip_text(stats)
def populate(self, contact): if not contact: return self.create_window() hbox = gtk.HBox() if contact.jid.strip() != "": info = '<span size="large" weight="bold">' + contact.jid + "</span>" else: info = '<span size="large" weight="bold">' + contact.name + "</span>" info += '\n<span weight="bold">' + _("Role: ") + "</span>" + helpers.get_uf_role(contact.role) info += '\n<span weight="bold">' + _("Affiliation: ") + "</span>" + contact.affiliation.capitalize() info += '\n<span weight="bold">' + _("Status: ") + "</span>" + helpers.get_uf_show(contact.show) if contact.status: status = contact.status.strip() if status != "": # escape markup entities info += " - " + gtkgui_helpers.escape_for_pango_markup(status) if contact.resource.strip() != "": info += ( '\n<span weight="bold">' + _("Resource: ") + "</span>" + gtkgui_helpers.escape_for_pango_markup(contact.resource) ) self.text_label.set_markup(info) hbox.add(self.text_label) self.win.add(hbox)
def __init__(self, show = None): self.show = show self.xml = gtk.glade.XML(GTKGUI_GLADE, 'change_status_message_dialog', APP) self.window = self.xml.get_widget('change_status_message_dialog') if show: uf_show = helpers.get_uf_show(show) title_text = _('%s Status Message') % uf_show else: title_text = _('Status Message') self.window.set_title(title_text) message_textview = self.xml.get_widget('message_textview') self.message_buffer = message_textview.get_buffer() msg = None if show: msg = gajim.config.get('last_status_msg_' + show) if not msg: msg = '' msg = helpers.from_one_line(msg) self.message_buffer.set_text(msg) self.values = {'':''} # have an empty string selectable, so user can clear msg for msg in gajim.config.get_per('statusmsg'): val = gajim.config.get_per('statusmsg', msg, 'message') val = helpers.from_one_line(val) self.values[msg] = val sorted_keys_list = helpers.get_sorted_keys(self.values) liststore = gtk.ListStore(str, str) message_comboboxentry = self.xml.get_widget('message_comboboxentry') message_comboboxentry.set_model(liststore) message_comboboxentry.set_text_column(0) message_comboboxentry.child.set_property('editable', False) for val in sorted_keys_list: message_comboboxentry.append_text(val) self.xml.signal_autoconnect(self) self.window.show_all()
def _fill_logs_listview(self, jid): '''fill the listview with all messages that user sent to or received from JID''' # no need to lower jid in this context as jid is already lowered # as we use those jids from db jid_id = self._get_jid_id(jid) self.cur.execute(''' SELECT log_line_id, jid_id, time, kind, message, subject, contact_name, show FROM logs WHERE jid_id = ? ORDER BY time ''', (jid_id,)) results = self.cur.fetchall() if self._jid_is_room_type(jid): # is it room? self.nickname_col_for_logs.set_visible(True) self.subject_col_for_logs.set_visible(False) else: self.nickname_col_for_logs.set_visible(False) self.subject_col_for_logs.set_visible(True) for row in results: # exposed in UI (TreeViewColumns) are only # time, message, subject, nickname # but store in liststore # log_line_id, jid_id, time, message, subject, nickname log_line_id, jid_id, time_, kind, message, subject, nickname, show = row try: time_ = time.strftime('%x', time.localtime(float(time_))).decode( locale.getpreferredencoding()) except ValueError: pass else: color = None if kind in (constants.KIND_SINGLE_MSG_RECV, constants.KIND_CHAT_MSG_RECV, constants.KIND_GC_MSG): # it is the other side color = gajim.config.get('inmsgcolor') # so incoming color elif kind in (constants.KIND_SINGLE_MSG_SENT, constants.KIND_CHAT_MSG_SENT): # it is us color = gajim.config.get('outmsgcolor') # so outgoing color elif kind in (constants.KIND_STATUS, constants.KIND_GCSTATUS): # is is statuses color = gajim.config.get('statusmsgcolor') # so status color # include status into (status) message if message is None: message = '' else: message = ' : ' + message message = helpers.get_uf_show(gajim.SHOW_LIST[show]) + message message_ = '<span' if color: message_ += ' foreground="%s"' % color message_ += '>%s</span>' % \ gobject.markup_escape_text(message) self.logs_liststore.append((log_line_id, jid_id, time_, message_, subject, nickname))
def fill_status_label(self): if self.xml.get_widget('information_notebook').get_n_pages() < 5: return contact_list = gajim.contacts.get_contacts(self.account, self.contact.jid) connected_contact_list = [] for c in contact_list: if c.show not in ('offline', 'error'): connected_contact_list.append(c) if not connected_contact_list: # no connected contact, get the offline one connected_contact_list = contact_list # stats holds show and status message stats = '' if connected_contact_list: # Start with self.contact, as with resources stats = helpers.get_uf_show(self.contact.show) if self.contact.status: stats += ': ' + self.contact.status if self.contact.last_status_time: stats += '\n' + _('since %s') % time.strftime( '%c', self.contact.last_status_time).decode( locale.getpreferredencoding()) for c in connected_contact_list: if c.resource != self.contact.resource: stats += '\n' stats += helpers.get_uf_show(c.show) if c.status: stats += ': ' + c.status if c.last_status_time: stats += '\n' + _('since %s') % time.strftime( '%c', c.last_status_time).decode( locale.getpreferredencoding()) else: # Maybe gc_vcard ? stats = helpers.get_uf_show(self.contact.show) if self.contact.status: stats += ': ' + self.contact.status status_label = self.xml.get_widget('status_label') status_label.set_max_width_chars(15) status_label.set_text(stats) tip = gtk.Tooltips() status_label_eventbox = self.xml.get_widget('status_label_eventbox') tip.set_tip(status_label_eventbox, stats)
def _set_idle_time(self, contact): 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: idle_color = gajim.config.get('tooltip_idle_color') idle_markup = "<span foreground='{}'>{}</span>".format(idle_color, formatted) self.idle_since.set_markup(idle_markup) self.idle_since.show() self.idle_since_label.show() idle_markup = "<span foreground='{}'>{}</span>".format(idle_color, str(diff)) self.idle_for.set_markup(idle_markup) self.idle_for_label.show() self.idle_for.show() if contact.show and self.num_resources < 2: show = helpers.get_uf_show(contact.show) if contact.last_status_time: 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 # Contact is Groupchat if (self.account and self.prim_contact.jid in gajim.gc_connected[self.account]): if gajim.gc_connected[self.account][self.prim_contact.jid]: show = _('Connected') else: show = _('Disconnected') self.user_show.set_markup(colorize_status(show)) self.user_show.show()
def fill_status_label(self): if self.xml.get_widget('information_notebook').get_n_pages() < 5: return contact_list = gajim.contacts.get_contacts(self.account, self.contact.jid) connected_contact_list = [] for c in contact_list: if c.show not in ('offline', 'error'): connected_contact_list.append(c) if not connected_contact_list: # no connected contact, get the offline one connected_contact_list = contact_list # stats holds show and status message stats = '' if connected_contact_list: # Start with self.contact, as with resources stats = helpers.get_uf_show(self.contact.show) if self.contact.status: stats += ': ' + self.contact.status if self.contact.last_status_time: stats += '\n' + _('since %s') % time.strftime('%c', self.contact.last_status_time).decode( locale.getpreferredencoding()) for c in connected_contact_list: if c.resource != self.contact.resource: stats += '\n' stats += helpers.get_uf_show(c.show) if c.status: stats += ': ' + c.status if c.last_status_time: stats += '\n' + _('since %s') % time.strftime('%c', c.last_status_time).decode(locale.getpreferredencoding()) else: # Maybe gc_vcard ? stats = helpers.get_uf_show(self.contact.show) if self.contact.status: stats += ': ' + self.contact.status status_label = self.xml.get_widget('status_label') status_label.set_max_width_chars(15) status_label.set_text(stats) tip = gtk.Tooltips() status_label_eventbox = self.xml.get_widget('status_label_eventbox') tip.set_tip(status_label_eventbox, stats)
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 get_accounts_info(self): accounts = [] if gajim.contacts: for account in gajim.contacts.keys(): status_idx = gajim.connections[account].connected # uncomment the following to hide offline accounts # if status_idx == 0: continue status = gajim.SHOW_LIST[status_idx] message = gajim.connections[account].status single_line = helpers.get_uf_show(status) if message is None: message = "" else: message = message.strip() if message != "": single_line += ": " + message # the other solution is to hide offline accounts elif status == "offline": message = helpers.get_uf_show(status) accounts.append({"name": account, "status_line": single_line, "show": status, "message": message}) return accounts
def fill_status_label(self): if self.xml.get_object("information_notebook").get_n_pages() < 5: return contact_list = gajim.contacts.get_contacts(self.account, self.contact.jid) connected_contact_list = [] for c in contact_list: if c.show not in ("offline", "error"): connected_contact_list.append(c) if not connected_contact_list: # no connected contact, get the offline one connected_contact_list = contact_list # stats holds show and status message stats = "" if connected_contact_list: # Start with self.contact, as with resources stats = helpers.get_uf_show(self.contact.show) if self.contact.status: stats += ": " + self.contact.status if self.contact.last_status_time: stats += "\n" + _("since %s") % time.strftime("%c", self.contact.last_status_time) for c in connected_contact_list: if c.resource != self.contact.resource: stats += "\n" stats += helpers.get_uf_show(c.show) if c.status: stats += ": " + c.status if c.last_status_time: stats += "\n" + _("since %s") % time.strftime("%c", c.last_status_time) else: # Maybe gc_vcard ? stats = helpers.get_uf_show(self.contact.show) if self.contact.status: stats += ": " + self.contact.status status_label = self.xml.get_object("status_label") status_label.set_max_width_chars(15) status_label.set_text(stats) status_label_eventbox = self.xml.get_object("status_label_eventbox") status_label_eventbox.set_tooltip_text(stats)
def set_treeview_string(self): (model, iter_) = self.conditions_treeview.get_selection().get_selected() if not iter_: return event = self.event_combobox.get_active_text() recipient_type = self.recipient_type_combobox.get_active_text() recipient = "" if recipient_type != "everybody": recipient = self.recipient_list_entry.get_text() if self.all_status_rb.get_active(): status = "" else: status = _("when I am ") for st in ("online", "away", "xa", "dnd", "invisible"): if self.__dict__[st + "_cb"].get_active(): status += helpers.get_uf_show(st) + " " model[iter_][1] = "When %s for %s %s %s" % (event, recipient_type, recipient, status)
def set_treeview_string(self): (model, iter_) = self.conditions_treeview.get_selection().get_selected() if not iter_: return event = self.event_combobox.get_active_text() recipient_type = self.recipient_type_combobox.get_active_text() recipient = '' if recipient_type != 'everybody': recipient = self.recipient_list_entry.get_text() if self.all_status_rb.get_active(): status = '' else: status = _('when I am ') for st in ('online', 'away', 'xa', 'dnd', 'invisible'): if self.__dict__[st + '_cb'].get_active(): status += helpers.get_uf_show(st) + ' ' model[iter_][1] = "When %s for %s %s %s" % (event, recipient_type, recipient, status)
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 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
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)
def get_transport_menu(contact, account): roster = gajim.interface.roster jid = contact.jid menu = Gtk.Menu() # Send single message item = Gtk.MenuItem.new_with_mnemonic(_('Send Single _Message...')) item.connect('activate', roster.on_send_single_message_menuitem_activate, account, contact) menu.append(item) if gajim.account_is_disconnected(account): item.set_sensitive(False) blocked = False if helpers.jid_is_blocked(account, jid): blocked = True # Send Custom Status send_custom_status_menuitem = Gtk.MenuItem.new_with_mnemonic( _('Send Cus_tom Status')) if blocked: send_custom_status_menuitem.set_sensitive(False) else: status_menuitems = Gtk.Menu() send_custom_status_menuitem.set_submenu(status_menuitems) for s in ('online', 'chat', 'away', 'xa', 'dnd', 'offline'): status_menuitem = Gtk.MenuItem.new_with_label( helpers.get_uf_show(s)) status_menuitem.connect('activate', roster.on_send_custom_status, [(contact, account)], s) status_menuitems.append(status_menuitem) menu.append(send_custom_status_menuitem) if gajim.account_is_disconnected(account): send_custom_status_menuitem.set_sensitive(False) item = Gtk.SeparatorMenuItem.new() # separator menu.append(item) # Execute Command item = Gtk.MenuItem.new_with_mnemonic(_('E_xecute Command...')) menu.append(item) item.connect('activate', roster.on_execute_command, contact, account, contact.resource) if gajim.account_is_disconnected(account): item.set_sensitive(False) # Manage Transport submenu item = Gtk.MenuItem.new_with_mnemonic(_('_Manage Transport')) manage_transport_submenu = Gtk.Menu() item.set_submenu(manage_transport_submenu) menu.append(item) # Modify Transport item = Gtk.MenuItem.new_with_mnemonic(_('_Modify Transport')) manage_transport_submenu.append(item) item.connect('activate', roster.on_edit_agent, contact, account) if gajim.account_is_disconnected(account): item.set_sensitive(False) # Rename item = Gtk.MenuItem.new_with_mnemonic(_('_Rename...')) manage_transport_submenu.append(item) item.connect('activate', roster.on_rename, 'agent', jid, account) if gajim.account_is_disconnected(account): item.set_sensitive(False) item = Gtk.SeparatorMenuItem.new() # separator manage_transport_submenu.append(item) # Block if blocked: item = Gtk.MenuItem.new_with_mnemonic(_('_Unblock')) item.connect('activate', roster.on_unblock, [(contact, account)]) else: item = Gtk.MenuItem.new_with_mnemonic(_('_Block')) item.connect('activate', roster.on_block, [(contact, account)]) manage_transport_submenu.append(item) if gajim.account_is_disconnected(account): item.set_sensitive(False) # Remove item = Gtk.MenuItem.new_with_mnemonic(_('Remo_ve')) manage_transport_submenu.append(item) item.connect('activate', roster.on_remove_agent, [(contact, account)]) if gajim.account_is_disconnected(account): item.set_sensitive(False) item = Gtk.SeparatorMenuItem.new() # separator menu.append(item) # Information information_menuitem = Gtk.MenuItem.new_with_mnemonic(_('_Information')) menu.append(information_menuitem) information_menuitem.connect('activate', roster.on_info, contact, account) if gajim.account_is_disconnected(account): information_menuitem.set_sensitive(False) menu.connect('selection-done', gtkgui_helpers.destroy_widget) menu.show_all() return menu
def _fill_logs_listview(self, jid): '''fill the listview with all messages that user sent to or received from JID''' # no need to lower jid in this context as jid is already lowered # as we use those jids from db jid_id = self._get_jid_id(jid) self.cur.execute( ''' SELECT log_line_id, jid_id, time, kind, message, subject, contact_name, show FROM logs WHERE jid_id = ? ORDER BY time ''', (jid_id, )) results = self.cur.fetchall() if self._jid_is_room_type(jid): # is it room? self.nickname_col_for_logs.set_visible(True) self.subject_col_for_logs.set_visible(False) else: self.nickname_col_for_logs.set_visible(False) self.subject_col_for_logs.set_visible(True) for row in results: # exposed in UI (TreeViewColumns) are only # time, message, subject, nickname # but store in liststore # log_line_id, jid_id, time, message, subject, nickname log_line_id, jid_id, time_, kind, message, subject, nickname, show = row try: time_ = time.strftime('%x', time.localtime( float(time_))).decode(locale.getpreferredencoding()) except ValueError: pass else: color = None if kind in (constants.KIND_SINGLE_MSG_RECV, constants.KIND_CHAT_MSG_RECV, constants.KIND_GC_MSG): # it is the other side color = gajim.config.get('inmsgcolor') # so incoming color elif kind in (constants.KIND_SINGLE_MSG_SENT, constants.KIND_CHAT_MSG_SENT): # it is us color = gajim.config.get( 'outmsgcolor') # so outgoing color elif kind in (constants.KIND_STATUS, constants.KIND_GCSTATUS): # is is statuses color = gajim.config.get( 'statusmsgcolor') # so status color # include status into (status) message if message is None: message = '' else: message = ' : ' + message message = helpers.get_uf_show( gajim.SHOW_LIST[show]) + message message_ = '<span' if color: message_ += ' foreground="%s"' % color message_ += '>%s</span>' % \ gobject.markup_escape_text(message) self.logs_liststore.append( (log_line_id, jid_id, time_, message_, subject, nickname))
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)
def add_new_line(self, contact_name, tim, kind, show, message): '''add a new line in textbuffer''' if not message: # None or '' return buf = self.history_buffer end_iter = buf.get_end_iter() if gajim.config.get('print_time') == 'always': before_str = gajim.config.get('before_time') after_str = gajim.config.get('after_time') format = before_str + '%X' + after_str + ' ' tim = time.strftime(format, time.localtime(float(tim))) buf.insert(end_iter, tim) # add time elif gajim.config.get('print_time') == 'sometimes': every_foo_seconds = 60 * gajim.config.get( 'print_ichat_every_foo_minutes') seconds_passed = tim - self.last_time_printout if seconds_passed > every_foo_seconds: self.last_time_printout = tim tim = time.strftime('%X ', time.localtime(float(tim))) buf.insert_with_tags_by_name(end_iter, tim + '\n', 'time_sometimes') tag_name = '' tag_msg = '' show = self.get_string_show_from_constant_int(show) if kind == constants.KIND_GC_MSG: tag_name = 'incoming' elif kind in (constants.KIND_SINGLE_MSG_RECV, constants.KIND_CHAT_MSG_RECV): try: # is he in our roster? if yes use the name contact_name = gajim.contacts[self.account][self.jid][0].name except: room_jid, nick = gajim.get_room_and_nick_from_fjid(self.jid) # do we have him as gc_contact? if nick and gajim.gc_contacts[self.account].has_key(room_jid) and\ gajim.gc_contacts[self.account][room_jid].has_key(nick): # so yes, it's pm! contact_name = nick else: contact_name = self.jid.split('@')[0] tag_name = 'incoming' elif kind in (constants.KIND_SINGLE_MSG_SENT, constants.KIND_CHAT_MSG_SENT): contact_name = gajim.nicks[self.account] tag_name = 'outgoing' elif kind == constants.KIND_GCSTATUS: # message here (if not None) is status message if message: message = _('%(nick)s is now %(status)s: %(status_msg)s') %\ {'nick': contact_name, 'status': helpers.get_uf_show(show), 'status_msg': message } else: message = _('%(nick)s is now %(status)s') % {'nick': contact_name, 'status': helpers.get_uf_show(show) } tag_msg = 'status' else: # 'status' # message here (if not None) is status message if message: message = _('Status is now: %(status)s: %(status_msg)s') % \ {'status': helpers.get_uf_show(show), 'status_msg': message} else: message = _('Status is now: %(status)s') % { 'status': helpers.get_uf_show(show) } tag_msg = 'status' # do not do this if gcstats, avoid dupping contact_name # eg. nkour: nkour is now Offline if contact_name and kind != constants.KIND_GCSTATUS: # add stuff before and after contact name before_str = gajim.config.get('before_nickname') after_str = gajim.config.get('after_nickname') format = before_str + contact_name + after_str + ' ' buf.insert_with_tags_by_name(end_iter, format, tag_name) message = message + '\n' if tag_msg: self.history_textview.print_real_text(message, [tag_msg]) else: self.history_textview.print_real_text(message)
def get_contact_menu(contact, account, use_multiple_contacts=True, show_start_chat=True, show_encryption=False, show_buttonbar_items=True, control=None, gc_contact=None, is_anonymous=True): """ Build contact popup menu for roster and chat window. If control is not set, we hide invite_contacts_menuitem """ if not contact: return jid = contact.jid our_jid = jid == gajim.get_jid_from_account(account) roster = gajim.interface.roster xml = gtkgui_helpers.get_gtk_builder('contact_context_menu.ui') contact_context_menu = xml.get_object('contact_context_menu') start_chat_menuitem = xml.get_object('start_chat_menuitem') execute_command_menuitem = xml.get_object('execute_command_menuitem') rename_menuitem = xml.get_object('rename_menuitem') edit_groups_menuitem = xml.get_object('edit_groups_menuitem') send_file_menuitem = xml.get_object('send_file_menuitem') assign_openpgp_key_menuitem = xml.get_object('assign_openpgp_key_menuitem') add_special_notification_menuitem = xml.get_object( 'add_special_notification_menuitem') information_menuitem = xml.get_object('information_menuitem') history_menuitem = xml.get_object('history_menuitem') send_custom_status_menuitem = xml.get_object('send_custom_status_menuitem') send_single_message_menuitem = xml.get_object('send_single_message_menuitem') invite_menuitem = xml.get_object('invite_menuitem') block_menuitem = xml.get_object('block_menuitem') unblock_menuitem = xml.get_object('unblock_menuitem') ignore_menuitem = xml.get_object('ignore_menuitem') unignore_menuitem = xml.get_object('unignore_menuitem') set_custom_avatar_menuitem = xml.get_object('set_custom_avatar_menuitem') # Subscription submenu subscription_menuitem = xml.get_object('subscription_menuitem') send_auth_menuitem, ask_auth_menuitem, revoke_auth_menuitem = \ subscription_menuitem.get_submenu().get_children() add_to_roster_menuitem = xml.get_object('add_to_roster_menuitem') remove_from_roster_menuitem = xml.get_object( 'remove_from_roster_menuitem') manage_contact_menuitem = xml.get_object('manage_contact') convert_to_gc_menuitem = xml.get_object('convert_to_groupchat_menuitem') encryption_separator = xml.get_object('encryption_separator') toggle_gpg_menuitem = xml.get_object('toggle_gpg_menuitem') toggle_e2e_menuitem = xml.get_object('toggle_e2e_menuitem') last_separator = xml.get_object('last_separator') items_to_hide = [] contacts = gajim.contacts.get_contacts(account, jid) if len(contacts) > 1 and use_multiple_contacts: # several resources start_chat_menuitem.set_submenu(build_resources_submenu(contacts, account, gajim.interface.on_open_chat_window)) send_file_menuitem.set_submenu(build_resources_submenu(contacts, account, roster.on_send_file_menuitem_activate, cap=NS_FILE)) execute_command_menuitem.set_submenu(build_resources_submenu( contacts, account, roster.on_execute_command, cap=NS_COMMANDS)) else: start_chat_menuitem.connect('activate', gajim.interface.on_open_chat_window, contact, account) if contact.supports(NS_FILE) or contact.supports(NS_JINGLE_FILE_TRANSFER): send_file_menuitem.set_sensitive(True) send_file_menuitem.connect('activate', roster.on_send_file_menuitem_activate, contact, account) else: send_file_menuitem.set_sensitive(False) if contact.supports(NS_COMMANDS): execute_command_menuitem.set_sensitive(True) if gc_contact and gc_contact.jid and not is_anonymous: execute_command_menuitem.connect('activate', roster.on_execute_command, gc_contact, account, gc_contact.resource) else: execute_command_menuitem.connect('activate', roster.on_execute_command, contact, account, contact.resource) else: execute_command_menuitem.set_sensitive(False) rename_menuitem.connect('activate', roster.on_rename, 'contact', jid, account) history_menuitem.connect('activate', roster.on_history, contact, account) if control: convert_to_gc_menuitem.connect('activate', control._on_convert_to_gc_menuitem_activate) else: items_to_hide.append(convert_to_gc_menuitem) if _('Not in Roster') not in contact.get_shown_groups(): # contact is in normal group edit_groups_menuitem.connect('activate', roster.on_edit_groups, [(contact, account)]) if gajim.connections[account].gpg: assign_openpgp_key_menuitem.connect('activate', roster.on_assign_pgp_key, contact, account) else: assign_openpgp_key_menuitem.set_sensitive(False) else: # contact is in group 'Not in Roster' edit_groups_menuitem.set_sensitive(False) assign_openpgp_key_menuitem.set_sensitive(False) # Hide items when it's self contact row if our_jid: items_to_hide += [rename_menuitem, edit_groups_menuitem] # Unsensitive many items when account is offline if gajim.account_is_disconnected(account): for widget in (start_chat_menuitem, rename_menuitem, edit_groups_menuitem, send_file_menuitem, convert_to_gc_menuitem, information_menuitem): widget.set_sensitive(False) if not show_start_chat: items_to_hide.append(start_chat_menuitem) if not show_encryption or not control: items_to_hide += [encryption_separator, toggle_gpg_menuitem, toggle_e2e_menuitem] else: e2e_is_active = control.session is not None and \ control.session.enable_encryption # check if we support and use gpg if not gajim.config.get_per('accounts', account, 'keyid') or \ not gajim.connections[account].USE_GPG or gajim.jid_is_transport( contact.jid): toggle_gpg_menuitem.set_sensitive(False) else: toggle_gpg_menuitem.set_sensitive(control.gpg_is_active or \ not e2e_is_active) toggle_gpg_menuitem.set_active(control.gpg_is_active) toggle_gpg_menuitem.connect('activate', control._on_toggle_gpg_menuitem_activate) # disable esessions if we or the other client don't support them if not gajim.HAVE_PYCRYPTO or not contact.supports(NS_ESESSION) or \ not gajim.config.get_per('accounts', account, 'enable_esessions'): toggle_e2e_menuitem.set_sensitive(False) else: toggle_e2e_menuitem.set_active(e2e_is_active) toggle_e2e_menuitem.set_sensitive(e2e_is_active or \ not control.gpg_is_active) toggle_e2e_menuitem.connect('activate', control._on_toggle_e2e_menuitem_activate) if not show_buttonbar_items: items_to_hide += [history_menuitem, send_file_menuitem, information_menuitem, convert_to_gc_menuitem, last_separator] if not control: items_to_hide.append(convert_to_gc_menuitem) # Hide items when it's a pm if gc_contact: items_to_hide += [rename_menuitem, edit_groups_menuitem, subscription_menuitem, remove_from_roster_menuitem] for item in items_to_hide: item.set_no_show_all(True) item.hide() # Zeroconf Account if gajim.config.get_per('accounts', account, 'is_zeroconf'): for item in (send_custom_status_menuitem, send_single_message_menuitem, invite_menuitem, block_menuitem, unblock_menuitem, ignore_menuitem, unignore_menuitem, set_custom_avatar_menuitem, subscription_menuitem, manage_contact_menuitem, convert_to_gc_menuitem): item.set_no_show_all(True) item.hide() if contact.show in ('offline', 'error'): information_menuitem.set_sensitive(False) send_file_menuitem.set_sensitive(False) else: information_menuitem.connect('activate', roster.on_info_zeroconf, contact, account) contact_context_menu.connect('selection-done', gtkgui_helpers.destroy_widget) contact_context_menu.show_all() return contact_context_menu # normal account # send custom status icon blocked = False if helpers.jid_is_blocked(account, jid): blocked = True else: for group in contact.get_shown_groups(): if helpers.group_is_blocked(account, group): blocked = True break transport = gajim.get_transport_name_from_jid(jid, use_config_setting=False) if transport and transport != 'jabber': # Transport contact, send custom status unavailable send_custom_status_menuitem.set_sensitive(False) elif blocked: send_custom_status_menuitem.set_sensitive(False) if gc_contact: if not gc_contact.jid: # it's a pm and we don't know real JID invite_menuitem.set_sensitive(False) else: bookmarked = False c_ = gajim.contacts.get_contact(account, gc_contact.jid, gc_contact.resource) if c_ and c_.supports(NS_CONFERENCE): bookmarked=True build_invite_submenu(invite_menuitem, [(gc_contact, account)], show_bookmarked=bookmarked) else: force_resource = False if control and control.resource: force_resource = True build_invite_submenu(invite_menuitem, [(contact, account)], show_bookmarked=contact.supports(NS_CONFERENCE), force_resource=force_resource) if gajim.account_is_disconnected(account): invite_menuitem.set_sensitive(False) # One or several resource, we do the same for send_custom_status status_menuitems = Gtk.Menu() send_custom_status_menuitem.set_submenu(status_menuitems) for s in ('online', 'chat', 'away', 'xa', 'dnd', 'offline'): # icon MUST be different instance for every item status_menuitem = Gtk.MenuItem.new_with_label(helpers.get_uf_show(s)) status_menuitem.connect('activate', roster.on_send_custom_status, [(contact, account)], s) status_menuitems.append(status_menuitem) send_single_message_menuitem.connect('activate', roster.on_send_single_message_menuitem_activate, account, contact) remove_from_roster_menuitem.connect('activate', roster.on_req_usub, [(contact, account)]) information_menuitem.connect('activate', roster.on_info, contact, account) if _('Not in Roster') not in contact.get_shown_groups(): # contact is in normal group add_to_roster_menuitem.hide() add_to_roster_menuitem.set_no_show_all(True) if contact.sub in ('from', 'both'): send_auth_menuitem.set_sensitive(False) else: send_auth_menuitem.connect('activate', roster.authorize, jid, account) if contact.sub in ('to', 'both'): ask_auth_menuitem.set_sensitive(False) add_special_notification_menuitem.connect('activate', roster.on_add_special_notification_menuitem_activate, jid) else: ask_auth_menuitem.connect('activate', roster.req_sub, jid, _('I would like to add you to my roster'), account, contact.groups, contact.name) transport = gajim.get_transport_name_from_jid(jid, use_config_setting=False) if contact.sub in ('to', 'none') or transport not in ['jabber', None]: revoke_auth_menuitem.set_sensitive(False) else: revoke_auth_menuitem.connect('activate', roster.revoke_auth, jid, account) elif gajim.connections[account].roster_supported: # contact is in group 'Not in Roster' add_to_roster_menuitem.set_no_show_all(False) subscription_menuitem.set_sensitive(False) add_to_roster_menuitem.connect('activate', roster.on_add_to_roster, contact, account) else: add_to_roster_menuitem.hide() add_to_roster_menuitem.set_no_show_all(True) subscription_menuitem.set_sensitive(False) set_custom_avatar_menuitem.connect('activate', roster.on_set_custom_avatar_activate, contact, account) # Hide items when it's self contact row if our_jid: manage_contact_menuitem.set_sensitive(False) # Unsensitive items when account is offline if gajim.account_is_disconnected(account): for widget in (send_single_message_menuitem, subscription_menuitem, add_to_roster_menuitem, remove_from_roster_menuitem, execute_command_menuitem, send_custom_status_menuitem): widget.set_sensitive(False) if gajim.connections[account] and (gajim.connections[account].\ privacy_rules_supported or gajim.connections[account].blocking_supported): if helpers.jid_is_blocked(account, jid): block_menuitem.set_no_show_all(True) block_menuitem.hide() if gajim.get_transport_name_from_jid(jid, use_config_setting=False)\ and transport != 'jabber': unblock_menuitem.set_no_show_all(True) unblock_menuitem.hide() unignore_menuitem.set_no_show_all(False) unignore_menuitem.connect('activate', roster.on_unblock, [(contact, account)]) else: unblock_menuitem.connect('activate', roster.on_unblock, [(contact, account)]) else: unblock_menuitem.set_no_show_all(True) unblock_menuitem.hide() if gajim.get_transport_name_from_jid(jid, use_config_setting=False)\ and transport != 'jabber': block_menuitem.set_no_show_all(True) block_menuitem.hide() ignore_menuitem.set_no_show_all(False) ignore_menuitem.connect('activate', roster.on_block, [(contact, account)]) else: block_menuitem.connect('activate', roster.on_block, [(contact, account)]) else: unblock_menuitem.set_no_show_all(True) block_menuitem.set_sensitive(False) unblock_menuitem.hide() contact_context_menu.connect('selection-done', gtkgui_helpers.destroy_widget) contact_context_menu.show_all() return contact_context_menu
def _add_new_line(self, contact_name, tim, kind, show, message, subject, additional_data): """ Add a new line in textbuffer """ if not message and kind not in (KindConstant.STATUS, KindConstant.GCSTATUS): return buf = self.history_buffer end_iter = buf.get_end_iter() if gajim.config.get('print_time') == 'always': timestamp_str = gajim.config.get('time_stamp') timestamp_str = helpers.from_one_line(timestamp_str) tim = time.strftime(timestamp_str, time.localtime(float(tim))) buf.insert(end_iter, tim) # add time elif gajim.config.get('print_time') == 'sometimes': every_foo_seconds = 60 * gajim.config.get( 'print_ichat_every_foo_minutes') seconds_passed = tim - self.last_time_printout if seconds_passed > every_foo_seconds: self.last_time_printout = tim tim = time.strftime('%X ', time.localtime(float(tim))) buf.insert_with_tags_by_name(end_iter, tim + '\n', 'time_sometimes') else: # don't print time. So we print it as invisible to be able to # search for it timestamp_str = gajim.config.get('time_stamp') timestamp_str = helpers.from_one_line(timestamp_str) tim = time.strftime(timestamp_str, time.localtime(float(tim))) buf.insert_with_tags_by_name(end_iter, tim, 'invisible') tag_name = '' tag_msg = '' show = self._get_string_show_from_constant_int(show) if kind == KindConstant.GC_MSG: tag_name = 'incoming' elif kind in (KindConstant.SINGLE_MSG_RECV, KindConstant.CHAT_MSG_RECV): contact_name = self.completion_dict[self.jid][InfoColumn.NAME] tag_name = 'incoming' tag_msg = 'incomingtxt' elif kind in (KindConstant.SINGLE_MSG_SENT, KindConstant.CHAT_MSG_SENT): if self.account: contact_name = gajim.nicks[self.account] else: # we don't have roster, we don't know our own nick, use first # account one (urk!) account = list(gajim.contacts.get_accounts())[0] contact_name = gajim.nicks[account] tag_name = 'outgoing' tag_msg = 'outgoingtxt' elif kind == KindConstant.GCSTATUS: # message here (if not None) is status message if message: message = _('%(nick)s is now %(status)s: %(status_msg)s') %\ {'nick': contact_name, 'status': helpers.get_uf_show(show), 'status_msg': message } else: message = _('%(nick)s is now %(status)s') % { 'nick': contact_name, 'status': helpers.get_uf_show(show) } tag_msg = 'status' else: # 'status' # message here (if not None) is status message if show is None: # it means error if message: message = _('Error: %s') % message else: message = _('Error') elif message: message = _('Status is now: %(status)s: %(status_msg)s') % \ {'status': helpers.get_uf_show(show), 'status_msg': message} else: message = _('Status is now: %(status)s') % { 'status': helpers.get_uf_show(show) } tag_msg = 'status' if message.startswith('/me ') or message.startswith('/me\n'): tag_msg = tag_name else: # do not do this if gcstats, avoid dupping contact_name # eg. nkour: nkour is now Offline if contact_name and kind != KindConstant.GCSTATUS: # add stuff before and after contact name before_str = gajim.config.get('before_nickname') before_str = helpers.from_one_line(before_str) after_str = gajim.config.get('after_nickname') after_str = helpers.from_one_line(after_str) format = before_str + contact_name + after_str + ' ' if tag_name: buf.insert_with_tags_by_name(end_iter, format, tag_name) else: buf.insert(end_iter, format) if subject: message = _('Subject: %s\n') % subject + message xhtml = None if message.startswith('<body '): xhtml = message if tag_msg: self.history_textview.print_real_text( message, [tag_msg], name=contact_name, xhtml=xhtml, additional_data=additional_data) else: self.history_textview.print_real_text( message, name=contact_name, xhtml=xhtml, additional_data=additional_data) buffer_ = self.history_textview.tv.get_buffer() eob = buffer_.get_end_iter() buffer_.insert_with_tags_by_name(eob, '\n', 'eol')
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 make_menu(self, event_button, event_time): '''create chat with and new message (sub) menus/menuitems''' for m in self.popup_menus: m.destroy() chat_with_menuitem = self.xml.get_widget('chat_with_menuitem') single_message_menuitem = self.xml.get_widget( 'single_message_menuitem') status_menuitem = self.xml.get_widget('status_menu') join_gc_menuitem = self.xml.get_widget('join_gc_menuitem') sounds_mute_menuitem = self.xml.get_widget('sounds_mute_menuitem') if self.single_message_handler_id: single_message_menuitem.handler_disconnect( self.single_message_handler_id) self.single_message_handler_id = None if self.new_chat_handler_id: chat_with_menuitem.disconnect(self.new_chat_handler_id) self.new_chat_handler_id = None sub_menu = gtk.Menu() self.popup_menus.append(sub_menu) status_menuitem.set_submenu(sub_menu) gc_sub_menu = gtk.Menu() # gc is always a submenu join_gc_menuitem.set_submenu(gc_sub_menu) # We need our own set of status icons, let's make 'em! iconset = gajim.config.get('iconset') path = os.path.join(helpers.get_iconset_path(iconset), '16x16') state_images = gtkgui_helpers.load_iconset(path) if 'muc_active' in state_images: join_gc_menuitem.set_image(state_images['muc_active']) for show in ('online', 'chat', 'away', 'xa', 'dnd', 'invisible'): uf_show = helpers.get_uf_show(show, use_mnemonic=True) item = gtk.ImageMenuItem(uf_show) item.set_image(state_images[show]) sub_menu.append(item) if os.name == 'nt': #FIXME: bug in pygtk, activate is not called. # see http://trac.gajim.org/ticket/4310 item.connect('button_press_event', self.on_show_menuitem_activate2, show) else: item.connect('activate', self.on_show_menuitem_activate, show) item = gtk.SeparatorMenuItem() sub_menu.append(item) item = gtk.ImageMenuItem(_('_Change Status Message...')) path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'kbd_input.png') img = gtk.Image() img.set_from_file(path) item.set_image(img) sub_menu.append(item) if os.name == 'nt': #FIXME: bug in pygtk, activate is not called. # see http://trac.gajim.org/ticket/4310 item.connect('button_press_event', self.on_change_status_message_activate2) else: item.connect('activate', self.on_change_status_message_activate) connected_accounts = gajim.get_number_of_connected_accounts() if connected_accounts < 1: item.set_sensitive(False) item = gtk.SeparatorMenuItem() sub_menu.append(item) uf_show = helpers.get_uf_show('offline', use_mnemonic=True) item = gtk.ImageMenuItem(uf_show) item.set_image(state_images['offline']) sub_menu.append(item) if os.name == 'nt': #FIXME: bug in pygtk, activate is not called. # see http://trac.gajim.org/ticket/4310 item.connect('button_press_event', self.on_show_menuitem_activate2, 'offline') else: item.connect('activate', self.on_show_menuitem_activate, 'offline') iskey = connected_accounts > 0 and not ( connected_accounts == 1 and gajim.connections[gajim.connections.keys()[0]].is_zeroconf) chat_with_menuitem.set_sensitive(iskey) single_message_menuitem.set_sensitive(iskey) join_gc_menuitem.set_sensitive(iskey) if connected_accounts >= 2: # 2 or more connections? make submenus account_menu_for_chat_with = gtk.Menu() chat_with_menuitem.set_submenu(account_menu_for_chat_with) self.popup_menus.append(account_menu_for_chat_with) account_menu_for_single_message = gtk.Menu() single_message_menuitem.set_submenu( account_menu_for_single_message) self.popup_menus.append(account_menu_for_single_message) accounts_list = sorted(gajim.contacts.get_accounts()) for account in accounts_list: if gajim.connections[account].is_zeroconf: continue if gajim.connections[account].connected > 1: # for chat_with item = gtk.MenuItem(_('using account %s') % account) account_menu_for_chat_with.append(item) if os.name == 'nt': #FIXME: bug in pygtk, activate is not called. # see http://trac.gajim.org/ticket/4310 item.connect('button_press_event', self.on_new_chat2, account) else: item.connect('activate', self.on_new_chat, account) # for single message item = gtk.MenuItem(_('using account %s') % account) if os.name == 'nt': #FIXME: bug in pygtk, activate is not called. # see http://trac.gajim.org/ticket/4310 item.connect('button_press_event', self.on_single_message_menuitem_activate2, account) else: item.connect('activate', self.on_single_message_menuitem_activate, account) account_menu_for_single_message.append(item) # join gc gc_item = gtk.MenuItem( _('using account %s') % account, False) gc_sub_menu.append(gc_item) gc_menuitem_menu = gtk.Menu() if os.name == 'nt': #FIXME: bug in pygtk, activate is not called. # see http://trac.gajim.org/ticket/4310 self.add_bookmarks_list2(gc_menuitem_menu, account) else: gajim.interface.roster.add_bookmarks_list( gc_menuitem_menu, account) gc_item.set_submenu(gc_menuitem_menu) gc_sub_menu.show_all() elif connected_accounts == 1: # one account # one account connected, no need to show 'as jid' for account in gajim.connections: if gajim.connections[account].connected > 1: self.new_chat_handler_id = chat_with_menuitem.connect( 'activate', self.on_new_chat, account) # for single message single_message_menuitem.remove_submenu() self.single_message_handler_id = single_message_menuitem.\ connect('activate', self.on_single_message_menuitem_activate, account) # join gc if os.name == 'nt': #FIXME: bug in pygtk, activate is not called. # see http://trac.gajim.org/ticket/4310 self.add_bookmarks_list2(gc_sub_menu, account) else: gajim.interface.roster.add_bookmarks_list( gc_sub_menu, account) break # No other connected account newitem = gtk.SeparatorMenuItem() # separator gc_sub_menu.append(newitem) newitem = gtk.ImageMenuItem(_('_Manage Bookmarks...')) img = gtk.image_new_from_stock(gtk.STOCK_PREFERENCES, gtk.ICON_SIZE_MENU) newitem.set_image(img) if os.name == 'nt': #FIXME: bug in pygtk, activate is not called. # see http://trac.gajim.org/ticket/4310 newitem.connect('button_press_event', self.on_manage_bookmarks_menuitem_activate2) else: newitem.connect( 'activate', gajim.interface.roster.on_manage_bookmarks_menuitem_activate) gc_sub_menu.append(newitem) sounds_mute_menuitem.set_active(not gajim.config.get('sounds_on')) if os.name == 'nt': if gtk.pygtk_version >= (2, 10, 0) and gtk.gtk_version >= (2, 10, 0): if self.added_hide_menuitem is False: self.systray_context_menu.prepend(gtk.SeparatorMenuItem()) item = gtk.MenuItem(_('Hide this menu')) self.systray_context_menu.prepend(item) self.added_hide_menuitem = True self.systray_context_menu.show_all() self.systray_context_menu.popup(None, None, None, event_button, event_time)
def populate(self, contact): if not contact: return self.create_window() vcard_table = gtk.Table(3, 1) vcard_table.set_property('column-spacing', 2) vcard_table.set_homogeneous(False) vcard_current_row = 1 properties = [] nick_markup = '<b>' + \ gobject.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>' +\ gobject.markup_escape_text(status) + '</i>' properties.append((status, None)) else: # no status message, show SHOW instead show = helpers.get_uf_show(contact.show) show = '<i>' + show + '</i>' properties.append((show, None)) if contact.jid.strip() != '': properties.append((_('Jabber ID: '), contact.jid)) if hasattr(contact, 'resource') and contact.resource.strip() != '': properties.append((_('Resource: '), gobject.markup_escape_text(contact.resource))) if contact.affiliation != 'none': uf_affiliation = helpers.get_uf_affiliation(contact.affiliation) affiliation_str = \ _('%(owner_or_admin_or_member)s of this group chat') %\ {'owner_or_admin_or_member': uf_affiliation} properties.append((affiliation_str, 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: 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) else: self.avatar_image.set_from_pixbuf(None) while properties: property = properties.pop(0) vcard_current_row += 1 vertical_fill = gtk.FILL if not properties: 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: label.set_markup(property[0]) label.set_line_wrap(True) 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) 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)
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 make_menu(self, event_button, event_time): """ Create chat with and new message (sub) menus/menuitems """ for m in self.popup_menus: m.destroy() chat_with_menuitem = self.xml.get_object('chat_with_menuitem') single_message_menuitem = self.xml.get_object( 'single_message_menuitem') status_menuitem = self.xml.get_object('status_menu') join_gc_menuitem = self.xml.get_object('join_gc_menuitem') sounds_mute_menuitem = self.xml.get_object('sounds_mute_menuitem') show_roster_menuitem = self.xml.get_object('show_roster_menuitem') if self.single_message_handler_id: single_message_menuitem.handler_disconnect( self.single_message_handler_id) self.single_message_handler_id = None if self.new_chat_handler_id: chat_with_menuitem.disconnect(self.new_chat_handler_id) self.new_chat_handler_id = None sub_menu = gtk.Menu() self.popup_menus.append(sub_menu) status_menuitem.set_submenu(sub_menu) gc_sub_menu = gtk.Menu() # gc is always a submenu join_gc_menuitem.set_submenu(gc_sub_menu) # We need our own set of status icons, let's make 'em! iconset = gajim.config.get('iconset') path = os.path.join(helpers.get_iconset_path(iconset), '16x16') state_images = gtkgui_helpers.load_iconset(path) if 'muc_active' in state_images: join_gc_menuitem.set_image(state_images['muc_active']) for show in ('online', 'chat', 'away', 'xa', 'dnd', 'invisible'): uf_show = helpers.get_uf_show(show, use_mnemonic = True) item = gtk.ImageMenuItem(uf_show) item.set_image(state_images[show]) sub_menu.append(item) item.connect('activate', self.on_show_menuitem_activate, show) item = gtk.SeparatorMenuItem() sub_menu.append(item) item = gtk.ImageMenuItem(_('_Change Status Message...')) gtkgui_helpers.add_image_to_menuitem(item, 'gajim-kbd_input') sub_menu.append(item) item.connect('activate', self.on_change_status_message_activate) connected_accounts = gajim.get_number_of_connected_accounts() if connected_accounts < 1: item.set_sensitive(False) connected_accounts_with_private_storage = 0 item = gtk.SeparatorMenuItem() sub_menu.append(item) uf_show = helpers.get_uf_show('offline', use_mnemonic = True) item = gtk.ImageMenuItem(uf_show) item.set_image(state_images['offline']) sub_menu.append(item) item.connect('activate', self.on_show_menuitem_activate, 'offline') iskey = connected_accounts > 0 and not (connected_accounts == 1 and gajim.zeroconf_is_connected()) chat_with_menuitem.set_sensitive(iskey) single_message_menuitem.set_sensitive(iskey) join_gc_menuitem.set_sensitive(iskey) accounts_list = sorted(gajim.contacts.get_accounts()) # items that get shown whether an account is zeroconf or not if connected_accounts > 1: # 2 or more connections? make submenus account_menu_for_chat_with = gtk.Menu() chat_with_menuitem.set_submenu(account_menu_for_chat_with) self.popup_menus.append(account_menu_for_chat_with) for account in accounts_list: if gajim.account_is_connected(account): # for chat_with item = gtk.MenuItem(_('using account %s') % account) account_menu_for_chat_with.append(item) item.connect('activate', self.on_new_chat, account) elif connected_accounts == 1: # one account # one account connected, no need to show 'as jid' for account in gajim.connections: if gajim.connections[account].connected > 1: # for start chat self.new_chat_handler_id = chat_with_menuitem.connect( 'activate', self.on_new_chat, account) break # No other connected account # menu items that don't apply to zeroconf connections if connected_accounts == 1 or (connected_accounts == 2 and \ gajim.zeroconf_is_connected()): # only one 'real' (non-zeroconf) account is connected, don't need # submenus for account in gajim.connections: if gajim.account_is_connected(account) and \ not gajim.config.get_per('accounts', account, 'is_zeroconf'): if gajim.connections[account].private_storage_supported: connected_accounts_with_private_storage += 1 # for single message single_message_menuitem.remove_submenu() self.single_message_handler_id = single_message_menuitem.\ connect('activate', self.on_single_message_menuitem_activate, account) # join gc gajim.interface.roster.add_bookmarks_list(gc_sub_menu, account) break # No other account connected else: # 2 or more 'real' accounts are connected, make submenus account_menu_for_single_message = gtk.Menu() single_message_menuitem.set_submenu( account_menu_for_single_message) self.popup_menus.append(account_menu_for_single_message) for account in accounts_list: if gajim.connections[account].is_zeroconf or \ not gajim.account_is_connected(account): continue if gajim.connections[account].private_storage_supported: connected_accounts_with_private_storage += 1 # for single message item = gtk.MenuItem(_('using account %s') % account) item.connect('activate', self.on_single_message_menuitem_activate, account) account_menu_for_single_message.append(item) # join gc gc_item = gtk.MenuItem(_('using account %s') % account, False) gc_sub_menu.append(gc_item) gc_menuitem_menu = gtk.Menu() gajim.interface.roster.add_bookmarks_list(gc_menuitem_menu, account) gc_item.set_submenu(gc_menuitem_menu) gc_sub_menu.show_all() newitem = gtk.SeparatorMenuItem() # separator gc_sub_menu.append(newitem) newitem = gtk.ImageMenuItem(_('_Manage Bookmarks...')) img = gtk.image_new_from_stock(gtk.STOCK_PREFERENCES, gtk.ICON_SIZE_MENU) newitem.set_image(img) newitem.connect('activate', gajim.interface.roster.on_manage_bookmarks_menuitem_activate) gc_sub_menu.append(newitem) if connected_accounts_with_private_storage == 0: newitem.set_sensitive(False) sounds_mute_menuitem.set_active(not gajim.config.get('sounds_on')) win = gajim.interface.roster.window if self.show_roster_handler_id: show_roster_menuitem.handler_disconnect(self.show_roster_handler_id) if win.get_property('has-toplevel-focus'): show_roster_menuitem.get_children()[0].set_label(_('Hide _Roster')) self.show_roster_handler_id = show_roster_menuitem.connect( 'activate', self.on_hide_roster_menuitem_activate) else: show_roster_menuitem.get_children()[0].set_label(_('Show _Roster')) self.show_roster_handler_id = show_roster_menuitem.connect( 'activate', self.on_show_roster_menuitem_activate) if os.name == 'nt': if self.added_hide_menuitem is False: self.systray_context_menu.prepend(gtk.SeparatorMenuItem()) item = gtk.MenuItem(_('Hide this menu')) self.systray_context_menu.prepend(item) self.added_hide_menuitem = True self.systray_context_menu.show_all() self.systray_context_menu.popup(None, None, None, 0, event_time)
def _add_new_line(self, contact_name, tim, kind, show, message): '''add a new line in textbuffer''' if not message and kind not in (constants.KIND_STATUS, constants.KIND_GCSTATUS): return buf = self.history_buffer end_iter = buf.get_end_iter() if gajim.config.get('print_time') == 'always': timestamp_str = gajim.config.get('time_stamp') timestamp_str = helpers.from_one_line(timestamp_str) tim = time.strftime(timestamp_str, time.localtime(float(tim))) buf.insert(end_iter, tim) # add time elif gajim.config.get('print_time') == 'sometimes': every_foo_seconds = 60 * gajim.config.get( 'print_ichat_every_foo_minutes') seconds_passed = tim - self.last_time_printout if seconds_passed > every_foo_seconds: self.last_time_printout = tim tim = time.strftime('%X ', time.localtime(float(tim))) buf.insert_with_tags_by_name(end_iter, tim + '\n', 'time_sometimes') tag_name = '' tag_msg = '' show = self._get_string_show_from_constant_int(show) if kind == constants.KIND_GC_MSG: tag_name = 'incoming' elif kind in (constants.KIND_SINGLE_MSG_RECV, constants.KIND_CHAT_MSG_RECV): contact_name = self.completion_dict[self.jid][C_INFO_NAME] tag_name = 'incoming' elif kind in (constants.KIND_SINGLE_MSG_SENT, constants.KIND_CHAT_MSG_SENT): if self.account: contact_name = gajim.nicks[self.account] else: # we don't have roster, we don't know our own nick, use first # account one (urk!) account = gajim.contacts.get_accounts()[0] contact_name = gajim.nicks[account] tag_name = 'outgoing' elif kind == constants.KIND_GCSTATUS: # message here (if not None) is status message if message: message = _('%(nick)s is now %(status)s: %(status_msg)s') %\ {'nick': contact_name, 'status': helpers.get_uf_show(show), 'status_msg': message } else: message = _('%(nick)s is now %(status)s') % {'nick': contact_name, 'status': helpers.get_uf_show(show) } tag_msg = 'status' else: # 'status' # message here (if not None) is status message if message: message = _('Status is now: %(status)s: %(status_msg)s') % \ {'status': helpers.get_uf_show(show), 'status_msg': message} else: message = _('Status is now: %(status)s') % { 'status': helpers.get_uf_show(show) } tag_msg = 'status' # do not do this if gcstats, avoid dupping contact_name # eg. nkour: nkour is now Offline if contact_name and kind != constants.KIND_GCSTATUS: # add stuff before and after contact name before_str = gajim.config.get('before_nickname') before_str = helpers.from_one_line(before_str) after_str = gajim.config.get('after_nickname') after_str = helpers.from_one_line(after_str) format = before_str + contact_name + after_str + ' ' buf.insert_with_tags_by_name(end_iter, format, tag_name) message = message + '\n' if tag_msg: self.history_textview.print_real_text(message, [tag_msg]) else: self.history_textview.print_real_text(message)
def populate(self, contact): if not contact: return self.create_window() vcard_table = gtk.Table(3, 1) vcard_table.set_property('column-spacing', 2) vcard_table.set_homogeneous(False) vcard_current_row = 1 properties = [] nick_markup = '<b>' + \ gobject.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>' +\ gobject.markup_escape_text(status) + '</i>' properties.append((status, None)) else: # no status message, show SHOW instead show = helpers.get_uf_show(contact.show) show = '<i>' + show + '</i>' properties.append((show, None)) if contact.jid.strip() != '': properties.append((_('Jabber ID: '), contact.jid)) if hasattr(contact, 'resource') and contact.resource.strip() != '': properties.append((_('Resource: '), gobject.markup_escape_text(contact.resource) )) if contact.affiliation != 'none': uf_affiliation = helpers.get_uf_affiliation(contact.affiliation) affiliation_str = \ _('%(owner_or_admin_or_member)s of this group chat') %\ {'owner_or_admin_or_member': uf_affiliation} properties.append((affiliation_str, 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: 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) else: self.avatar_image.set_from_pixbuf(None) while properties: property = properties.pop(0) vcard_current_row += 1 vertical_fill = gtk.FILL if not properties: 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: label.set_markup(property[0]) label.set_line_wrap(True) 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) 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)
def make_menu(self, event = None): '''create chat with and new message (sub) menus/menuitems event is None when we're in Windows ''' chat_with_menuitem = self.xml.get_widget('chat_with_menuitem') new_message_menuitem = self.xml.get_widget('new_message_menuitem') status_menuitem = self.xml.get_widget('status_menu') if self.new_message_handler_id: new_message_menuitem.handler_disconnect( self.new_message_handler_id) self.new_message_handler_id = None sub_menu = gtk.Menu() status_menuitem.set_submenu(sub_menu) # We need our own set of status icons, let's make 'em! iconset = gajim.config.get('iconset') if not iconset: iconset = 'dcraven' path = os.path.join(gajim.DATA_DIR, 'iconsets', iconset, '16x16') state_images = gajim.interface.roster.load_iconset(path) for show in ('online', 'chat', 'away', 'xa', 'dnd', 'invisible'): uf_show = helpers.get_uf_show(show, use_mnemonic = True) item = gtk.ImageMenuItem(uf_show) item.set_image(state_images[show]) sub_menu.append(item) item.connect('activate', self.on_show_menuitem_activate, show) item = gtk.SeparatorMenuItem() sub_menu.append(item) item = gtk.ImageMenuItem(_('_Change Status Message...')) path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'rename.png') img = gtk.Image() img.set_from_file(path) item.set_image(img) sub_menu.append(item) item.connect('activate', self.on_change_status_message_activate) if not helpers.one_account_connected(): item.set_sensitive(False) item = gtk.SeparatorMenuItem() sub_menu.append(item) uf_show = helpers.get_uf_show('offline', use_mnemonic = True) item = gtk.ImageMenuItem(uf_show) item.set_image(state_images['offline']) sub_menu.append(item) item.connect('activate', self.on_show_menuitem_activate, 'offline') iskey = len(gajim.connections) > 0 chat_with_menuitem.set_sensitive(iskey) new_message_menuitem.set_sensitive(iskey) if len(gajim.connections) >= 2: # 2 or more connections? make submenus account_menu_for_chat_with = gtk.Menu() chat_with_menuitem.set_submenu(account_menu_for_chat_with) account_menu_for_new_message = gtk.Menu() new_message_menuitem.set_submenu(account_menu_for_new_message) for account in gajim.connections: #for chat_with item = gtk.MenuItem(_('using account ') + account) account_menu_for_chat_with.append(item) group_menu = self.make_groups_submenus_for_chat_with(account) item.set_submenu(group_menu) #for new_message item = gtk.MenuItem(_('using account ') + account) item.connect('activate', self.on_new_message_menuitem_activate, account) account_menu_for_new_message.append(item) elif len(gajim.connections) == 1: # one account # one account, no need to show 'as jid' # for chat_with account = gajim.connections.keys()[0] group_menu = self.make_groups_submenus_for_chat_with(account) chat_with_menuitem.set_submenu(group_menu) # for new message self.new_message_handler_id = new_message_menuitem.connect( 'activate', self.on_new_message_menuitem_activate, account) if event is None: # None means windows (we explicitly popup in systraywin32.py) if self.added_hide_menuitem is False: self.systray_context_menu.prepend(gtk.SeparatorMenuItem()) item = gtk.MenuItem(_('Hide this menu')) self.systray_context_menu.prepend(item) self.added_hide_menuitem = True else: # GNU and Unices self.systray_context_menu.popup(None, None, None, event.button, event.time) self.systray_context_menu.show_all()
def populate(self, data): self.create_window() self.create_table() self.hbox = gtk.HBox() self.table.set_property("column-spacing", 1) text, single_line = "", "" unread_chat = gajim.interface.roster.nb_unread unread_single_chat = 0 unread_gc = 0 unread_pm = 0 accounts = self.get_accounts_info() for acct in gajim.connections: # we count unread chat/pm messages chat_wins = gajim.interface.instances[acct]["chats"] for jid in chat_wins: if jid != "tabbed": if gajim.contacts[acct].has_key(jid): unread_chat += chat_wins[jid].nb_unread[jid] else: unread_pm += chat_wins[jid].nb_unread[jid] # we count unread gc/pm messages gc_wins = gajim.interface.instances[acct]["gc"] for jid in gc_wins: if jid != "tabbed": pm_msgs = gc_wins[jid].get_specific_unread(jid) unread_gc += gc_wins[jid].nb_unread[jid] unread_gc -= pm_msgs unread_pm += pm_msgs if unread_chat or unread_single_chat or unread_gc or unread_pm: text = "" if unread_chat: text += i18n.ngettext( "Gajim - %d unread message", "Gajim - %d unread messages", unread_chat, unread_chat, unread_chat ) text += "\n" if unread_single_chat: text += i18n.ngettext( "Gajim - %d unread single message", "Gajim - %d unread single messages", unread_single_chat, unread_single_chat, unread_single_chat, ) text += "\n" if unread_gc: text += i18n.ngettext( "Gajim - %d unread group chat message", "Gajim - %d unread group chat messages", unread_gc, unread_gc, unread_gc, ) text += "\n" if unread_pm: text += i18n.ngettext( "Gajim - %d unread private message", "Gajim - %d unread private messages", unread_pm, unread_pm, unread_pm, ) text += "\n" text = text[:-1] # remove latest \n elif len(accounts) > 1: text = _("Gajim") self.current_row = 1 self.table.resize(2, 1) self.fill_table_with_accounts(accounts) elif len(accounts) == 1: message = accounts[0]["status_line"] message = gtkgui_helpers.reduce_chars_newlines(message, 50, 1) message = gtkgui_helpers.escape_for_pango_markup(message) text = _("Gajim - %s") % message else: text = _("Gajim - %s") % helpers.get_uf_show("offline") self.text_label.set_markup(text) self.hbox.add(self.table) self.win.add(self.hbox)
def populate(self, contacts): self.create_window() self.hbox = gtk.HBox() self.hbox.set_homogeneous(False) self.hbox.set_spacing(0) self.create_table() if not contacts or len(contacts) == 0: # Tooltip for merged accounts row accounts = self.get_accounts_info() self.current_row = 0 self.table.resize(2, 1) self.spacer_label = "" self.fill_table_with_accounts(accounts) self.hbox.add(self.table) self.win.add(self.hbox) return # primary contact prim_contact = gajim.get_highest_prio_contact_from_contacts(contacts) # try to find the image for the contact status icon_name = helpers.get_icon_name_to_show(prim_contact) state_file = icon_name.replace(" ", "_") transport = gajim.get_transport_name_from_jid(prim_contact.jid) if transport: file_path = os.path.join(gajim.DATA_DIR, "iconsets", "transports", transport, "16x16") else: iconset = gajim.config.get("iconset") if not iconset: iconset = "dcraven" file_path = os.path.join(gajim.DATA_DIR, "iconsets", iconset, "16x16") files = [] file_full_path = os.path.join(file_path, state_file) files.append(file_full_path + ".png") files.append(file_full_path + ".gif") self.image.set_from_pixbuf(None) for file in files: if os.path.exists(file): self.image.set_from_file(file) break info = '<span size="large" weight="bold">' + prim_contact.jid + "</span>" info += ( '\n<span weight="bold">' + _("Name: ") + "</span>" + gtkgui_helpers.escape_for_pango_markup(prim_contact.name) ) if prim_contact.sub: info += ( '\n<span weight="bold">' + _("Subscription: ") + "</span>" + gtkgui_helpers.escape_for_pango_markup(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: info += ( '\n<span weight="bold">' + _("OpenPGP: ") + "</span>" + gtkgui_helpers.escape_for_pango_markup(keyID) ) num_resources = 0 for contact in contacts: if contact.resource: num_resources += 1 if num_resources > 1: self.current_row = 1 self.table.resize(2, 1) info += '\n<span weight="bold">' + _("Status: ") + "</span>" for contact in contacts: if contact.resource: status_line = self.get_status_info(contact.resource, contact.priority, contact.show, contact.status) icon_name = helpers.get_icon_name_to_show(contact) self.add_status_row(file_path, icon_name, status_line) else: # only one resource if contact.resource: info += ( '\n<span weight="bold">' + _("Resource: ") + "</span>" + gtkgui_helpers.escape_for_pango_markup(contact.resource) + " (" + unicode(contact.priority) + ")" ) if contact.show: info += '\n<span weight="bold">' + _("Status: ") + "</span>" + helpers.get_uf_show(contact.show) if contact.status: status = contact.status.strip() if status != "": # reduce long status # (no more than 130 chars on line and no more than 5 lines) status = gtkgui_helpers.reduce_chars_newlines(status, 130, 5) # escape markup entities. info += " - " + gtkgui_helpers.escape_for_pango_markup(status) self.text_label.set_markup(info) self.hbox.pack_start(self.image, False, False) self.hbox.pack_start(self.table, True, True) self.win.add(self.hbox)
def get_contact_menu(contact, account, use_multiple_contacts=True, show_start_chat=True, show_encryption=False, show_buttonbar_items=True, control=None, gc_contact=None, is_anonymous=True): """ Build contact popup menu for roster and chat window. If control is not set, we hide invite_contacts_menuitem """ if not contact: return jid = contact.jid our_jid = jid == gajim.get_jid_from_account(account) roster = gajim.interface.roster xml = gtkgui_helpers.get_gtk_builder('contact_context_menu.ui') contact_context_menu = xml.get_object('contact_context_menu') start_chat_menuitem = xml.get_object('start_chat_menuitem') execute_command_menuitem = xml.get_object('execute_command_menuitem') rename_menuitem = xml.get_object('rename_menuitem') edit_groups_menuitem = xml.get_object('edit_groups_menuitem') send_file_menuitem = xml.get_object('send_file_menuitem') assign_openpgp_key_menuitem = xml.get_object('assign_openpgp_key_menuitem') add_special_notification_menuitem = xml.get_object( 'add_special_notification_menuitem') information_menuitem = xml.get_object('information_menuitem') history_menuitem = xml.get_object('history_menuitem') send_custom_status_menuitem = xml.get_object('send_custom_status_menuitem') send_single_message_menuitem = xml.get_object( 'send_single_message_menuitem') invite_menuitem = xml.get_object('invite_menuitem') block_menuitem = xml.get_object('block_menuitem') unblock_menuitem = xml.get_object('unblock_menuitem') ignore_menuitem = xml.get_object('ignore_menuitem') unignore_menuitem = xml.get_object('unignore_menuitem') set_custom_avatar_menuitem = xml.get_object('set_custom_avatar_menuitem') # Subscription submenu subscription_menuitem = xml.get_object('subscription_menuitem') send_auth_menuitem, ask_auth_menuitem, revoke_auth_menuitem = \ subscription_menuitem.get_submenu().get_children() add_to_roster_menuitem = xml.get_object('add_to_roster_menuitem') remove_from_roster_menuitem = xml.get_object('remove_from_roster_menuitem') manage_contact_menuitem = xml.get_object('manage_contact') convert_to_gc_menuitem = xml.get_object('convert_to_groupchat_menuitem') encryption_separator = xml.get_object('encryption_separator') toggle_gpg_menuitem = xml.get_object('toggle_gpg_menuitem') toggle_e2e_menuitem = xml.get_object('toggle_e2e_menuitem') last_separator = xml.get_object('last_separator') items_to_hide = [] contacts = gajim.contacts.get_contacts(account, jid) if len(contacts) > 1 and use_multiple_contacts: # several resources start_chat_menuitem.set_submenu( build_resources_submenu(contacts, account, gajim.interface.on_open_chat_window)) send_file_menuitem.set_submenu( build_resources_submenu(contacts, account, roster.on_send_file_menuitem_activate, cap=NS_FILE)) execute_command_menuitem.set_submenu( build_resources_submenu(contacts, account, roster.on_execute_command, cap=NS_COMMANDS)) else: start_chat_menuitem.connect('activate', gajim.interface.on_open_chat_window, contact, account) if contact.supports(NS_FILE) or contact.supports( NS_JINGLE_FILE_TRANSFER): send_file_menuitem.set_sensitive(True) send_file_menuitem.connect('activate', roster.on_send_file_menuitem_activate, contact, account) else: send_file_menuitem.set_sensitive(False) if contact.supports(NS_COMMANDS): execute_command_menuitem.set_sensitive(True) if gc_contact and gc_contact.jid and not is_anonymous: execute_command_menuitem.connect('activate', roster.on_execute_command, gc_contact, account, gc_contact.resource) else: execute_command_menuitem.connect('activate', roster.on_execute_command, contact, account, contact.resource) else: execute_command_menuitem.set_sensitive(False) rename_menuitem.connect('activate', roster.on_rename, 'contact', jid, account) history_menuitem.connect('activate', roster.on_history, contact, account) if control: convert_to_gc_menuitem.connect( 'activate', control._on_convert_to_gc_menuitem_activate) else: items_to_hide.append(convert_to_gc_menuitem) if _('Not in Roster') not in contact.get_shown_groups(): # contact is in normal group edit_groups_menuitem.connect('activate', roster.on_edit_groups, [(contact, account)]) if gajim.connections[account].gpg: assign_openpgp_key_menuitem.connect('activate', roster.on_assign_pgp_key, contact, account) else: assign_openpgp_key_menuitem.set_sensitive(False) else: # contact is in group 'Not in Roster' edit_groups_menuitem.set_sensitive(False) assign_openpgp_key_menuitem.set_sensitive(False) # Hide items when it's self contact row if our_jid: items_to_hide += [rename_menuitem, edit_groups_menuitem] # Unsensitive many items when account is offline if gajim.account_is_disconnected(account): for widget in (start_chat_menuitem, rename_menuitem, edit_groups_menuitem, send_file_menuitem, convert_to_gc_menuitem, information_menuitem): widget.set_sensitive(False) if not show_start_chat: items_to_hide.append(start_chat_menuitem) if not show_encryption or not control: items_to_hide += [ encryption_separator, toggle_gpg_menuitem, toggle_e2e_menuitem ] else: e2e_is_active = control.session is not None and \ control.session.enable_encryption # check if we support and use gpg if not gajim.config.get_per('accounts', account, 'keyid') or \ not gajim.connections[account].USE_GPG or gajim.jid_is_transport( contact.jid): toggle_gpg_menuitem.set_sensitive(False) else: toggle_gpg_menuitem.set_sensitive(control.gpg_is_active or \ not e2e_is_active) toggle_gpg_menuitem.set_active(control.gpg_is_active) toggle_gpg_menuitem.connect( 'activate', control._on_toggle_gpg_menuitem_activate) # disable esessions if we or the other client don't support them if not gajim.HAVE_PYCRYPTO or not contact.supports(NS_ESESSION) or \ not gajim.config.get_per('accounts', account, 'enable_esessions'): toggle_e2e_menuitem.set_sensitive(False) else: toggle_e2e_menuitem.set_active(e2e_is_active) toggle_e2e_menuitem.set_sensitive(e2e_is_active or \ not control.gpg_is_active) toggle_e2e_menuitem.connect( 'activate', control._on_toggle_e2e_menuitem_activate) if not show_buttonbar_items: items_to_hide += [ history_menuitem, send_file_menuitem, information_menuitem, convert_to_gc_menuitem, last_separator ] if not control: items_to_hide.append(convert_to_gc_menuitem) # Hide items when it's a pm if gc_contact: items_to_hide += [ rename_menuitem, edit_groups_menuitem, subscription_menuitem, remove_from_roster_menuitem ] for item in items_to_hide: item.set_no_show_all(True) item.hide() # Zeroconf Account if gajim.config.get_per('accounts', account, 'is_zeroconf'): for item in (send_custom_status_menuitem, send_single_message_menuitem, invite_menuitem, block_menuitem, unblock_menuitem, ignore_menuitem, unignore_menuitem, set_custom_avatar_menuitem, subscription_menuitem, manage_contact_menuitem, convert_to_gc_menuitem): item.set_no_show_all(True) item.hide() if contact.show in ('offline', 'error'): information_menuitem.set_sensitive(False) send_file_menuitem.set_sensitive(False) else: information_menuitem.connect('activate', roster.on_info_zeroconf, contact, account) contact_context_menu.connect('selection-done', gtkgui_helpers.destroy_widget) contact_context_menu.show_all() return contact_context_menu # normal account # send custom status icon blocked = False if helpers.jid_is_blocked(account, jid): blocked = True else: for group in contact.get_shown_groups(): if helpers.group_is_blocked(account, group): blocked = True break transport = gajim.get_transport_name_from_jid(jid, use_config_setting=False) if transport and transport != 'jabber': # Transport contact, send custom status unavailable send_custom_status_menuitem.set_sensitive(False) elif blocked: send_custom_status_menuitem.set_sensitive(False) if gc_contact: if not gc_contact.jid: # it's a pm and we don't know real JID invite_menuitem.set_sensitive(False) else: bookmarked = False c_ = gajim.contacts.get_contact(account, gc_contact.jid, gc_contact.resource) if c_ and c_.supports(NS_CONFERENCE): bookmarked = True build_invite_submenu(invite_menuitem, [(gc_contact, account)], show_bookmarked=bookmarked) else: force_resource = False if control and control.resource: force_resource = True build_invite_submenu(invite_menuitem, [(contact, account)], show_bookmarked=contact.supports(NS_CONFERENCE), force_resource=force_resource) if gajim.account_is_disconnected(account): invite_menuitem.set_sensitive(False) # One or several resource, we do the same for send_custom_status status_menuitems = Gtk.Menu() send_custom_status_menuitem.set_submenu(status_menuitems) for s in ('online', 'chat', 'away', 'xa', 'dnd', 'offline'): # icon MUST be different instance for every item status_menuitem = Gtk.MenuItem.new_with_label(helpers.get_uf_show(s)) status_menuitem.connect('activate', roster.on_send_custom_status, [(contact, account)], s) status_menuitems.append(status_menuitem) send_single_message_menuitem.connect( 'activate', roster.on_send_single_message_menuitem_activate, account, contact) remove_from_roster_menuitem.connect('activate', roster.on_req_usub, [(contact, account)]) information_menuitem.connect('activate', roster.on_info, contact, account) if _('Not in Roster') not in contact.get_shown_groups(): # contact is in normal group add_to_roster_menuitem.hide() add_to_roster_menuitem.set_no_show_all(True) if contact.sub in ('from', 'both'): send_auth_menuitem.set_sensitive(False) else: send_auth_menuitem.connect('activate', roster.authorize, jid, account) if contact.sub in ('to', 'both'): ask_auth_menuitem.set_sensitive(False) add_special_notification_menuitem.connect( 'activate', roster.on_add_special_notification_menuitem_activate, jid) else: ask_auth_menuitem.connect( 'activate', roster.req_sub, jid, _('I would like to add you to my roster'), account, contact.groups, contact.name) transport = gajim.get_transport_name_from_jid(jid, use_config_setting=False) if contact.sub in ('to', 'none') or transport not in ['jabber', None]: revoke_auth_menuitem.set_sensitive(False) else: revoke_auth_menuitem.connect('activate', roster.revoke_auth, jid, account) elif gajim.connections[account].roster_supported: # contact is in group 'Not in Roster' add_to_roster_menuitem.set_no_show_all(False) subscription_menuitem.set_sensitive(False) add_to_roster_menuitem.connect('activate', roster.on_add_to_roster, contact, account) else: add_to_roster_menuitem.hide() add_to_roster_menuitem.set_no_show_all(True) subscription_menuitem.set_sensitive(False) set_custom_avatar_menuitem.connect('activate', roster.on_set_custom_avatar_activate, contact, account) # Hide items when it's self contact row if our_jid: manage_contact_menuitem.set_sensitive(False) # Unsensitive items when account is offline if gajim.account_is_disconnected(account): for widget in (send_single_message_menuitem, subscription_menuitem, add_to_roster_menuitem, remove_from_roster_menuitem, execute_command_menuitem, send_custom_status_menuitem): widget.set_sensitive(False) if gajim.connections[account] and (gajim.connections[account].\ privacy_rules_supported or gajim.connections[account].blocking_supported): if helpers.jid_is_blocked(account, jid): block_menuitem.set_no_show_all(True) block_menuitem.hide() if gajim.get_transport_name_from_jid(jid, use_config_setting=False)\ and transport != 'jabber': unblock_menuitem.set_no_show_all(True) unblock_menuitem.hide() unignore_menuitem.set_no_show_all(False) unignore_menuitem.connect('activate', roster.on_unblock, [(contact, account)]) else: unblock_menuitem.connect('activate', roster.on_unblock, [(contact, account)]) else: unblock_menuitem.set_no_show_all(True) unblock_menuitem.hide() if gajim.get_transport_name_from_jid(jid, use_config_setting=False)\ and transport != 'jabber': block_menuitem.set_no_show_all(True) block_menuitem.hide() ignore_menuitem.set_no_show_all(False) ignore_menuitem.connect('activate', roster.on_block, [(contact, account)]) else: block_menuitem.connect('activate', roster.on_block, [(contact, account)]) else: unblock_menuitem.set_no_show_all(True) block_menuitem.set_sensitive(False) unblock_menuitem.hide() contact_context_menu.connect('selection-done', gtkgui_helpers.destroy_widget) contact_context_menu.show_all() return contact_context_menu
def make_menu(self, event_button, event_time): """ Create chat with and new message (sub) menus/menuitems """ for m in self.popup_menus: m.destroy() chat_with_menuitem = self.xml.get_object('chat_with_menuitem') single_message_menuitem = self.xml.get_object( 'single_message_menuitem') status_menuitem = self.xml.get_object('status_menu') join_gc_menuitem = self.xml.get_object('join_gc_menuitem') sounds_mute_menuitem = self.xml.get_object('sounds_mute_menuitem') show_roster_menuitem = self.xml.get_object('show_roster_menuitem') if self.single_message_handler_id: single_message_menuitem.handler_disconnect( self.single_message_handler_id) self.single_message_handler_id = None if self.new_chat_handler_id: chat_with_menuitem.disconnect(self.new_chat_handler_id) self.new_chat_handler_id = None sub_menu = Gtk.Menu() self.popup_menus.append(sub_menu) status_menuitem.set_submenu(sub_menu) gc_sub_menu = Gtk.Menu() # gc is always a submenu join_gc_menuitem.set_submenu(gc_sub_menu) # We need our own set of status icons, let's make 'em! iconset = gajim.config.get('iconset') path = os.path.join(helpers.get_iconset_path(iconset), '16x16') for show in ('online', 'chat', 'away', 'xa', 'dnd', 'invisible'): uf_show = helpers.get_uf_show(show, use_mnemonic=True) item = Gtk.MenuItem.new_with_mnemonic(uf_show) sub_menu.append(item) item.connect('activate', self.on_show_menuitem_activate, show) item = Gtk.SeparatorMenuItem.new() sub_menu.append(item) item = Gtk.MenuItem.new_with_mnemonic(_('_Change Status Message…')) sub_menu.append(item) item.connect('activate', self.on_change_status_message_activate) connected_accounts = gajim.get_number_of_connected_accounts() if connected_accounts < 1: item.set_sensitive(False) connected_accounts_with_private_storage = 0 item = Gtk.SeparatorMenuItem.new() sub_menu.append(item) uf_show = helpers.get_uf_show('offline', use_mnemonic=True) item = Gtk.MenuItem.new_with_mnemonic(uf_show) sub_menu.append(item) item.connect('activate', self.on_show_menuitem_activate, 'offline') iskey = connected_accounts > 0 and not (connected_accounts == 1 and gajim.zeroconf_is_connected()) chat_with_menuitem.set_sensitive(iskey) single_message_menuitem.set_sensitive(iskey) join_gc_menuitem.set_sensitive(iskey) accounts_list = sorted(gajim.contacts.get_accounts()) # items that get shown whether an account is zeroconf or not if connected_accounts > 1: # 2 or more connections? make submenus account_menu_for_chat_with = Gtk.Menu() chat_with_menuitem.set_submenu(account_menu_for_chat_with) self.popup_menus.append(account_menu_for_chat_with) for account in accounts_list: if gajim.account_is_connected(account): # for chat_with item = Gtk.MenuItem.new_with_label( _('using account %s') % account) account_menu_for_chat_with.append(item) item.connect('activate', self.on_new_chat, account) elif connected_accounts == 1: # one account # one account connected, no need to show 'as jid' for account in gajim.connections: if gajim.connections[account].connected > 1: # for start chat self.new_chat_handler_id = chat_with_menuitem.connect( 'activate', self.on_new_chat, account) break # No other connected account # menu items that don't apply to zeroconf connections if connected_accounts == 1 or (connected_accounts == 2 and \ gajim.zeroconf_is_connected()): # only one 'real' (non-zeroconf) account is connected, don't need # submenus for account in gajim.connections: if gajim.account_is_connected(account) and \ not gajim.config.get_per('accounts', account, 'is_zeroconf'): if gajim.connections[account].private_storage_supported: connected_accounts_with_private_storage += 1 # for single message single_message_menuitem.set_submenu(None) self.single_message_handler_id = single_message_menuitem.\ connect('activate', self.on_single_message_menuitem_activate, account) # join gc gajim.interface.roster.add_bookmarks_list(gc_sub_menu, account) break # No other account connected else: # 2 or more 'real' accounts are connected, make submenus account_menu_for_single_message = Gtk.Menu() single_message_menuitem.set_submenu( account_menu_for_single_message) self.popup_menus.append(account_menu_for_single_message) for account in accounts_list: if gajim.connections[account].is_zeroconf or \ not gajim.account_is_connected(account): continue if gajim.connections[account].private_storage_supported: connected_accounts_with_private_storage += 1 # for single message item = Gtk.MenuItem.new_with_label( _('using account %s') % account) item.connect('activate', self.on_single_message_menuitem_activate, account) account_menu_for_single_message.append(item) # join gc gc_item = Gtk.MenuItem.new_with_label( _('using account %s') % account) gc_sub_menu.append(gc_item) gc_menuitem_menu = Gtk.Menu() gajim.interface.roster.add_bookmarks_list(gc_menuitem_menu, account) gc_item.set_submenu(gc_menuitem_menu) gc_sub_menu.show_all() newitem = Gtk.SeparatorMenuItem.new() # separator gc_sub_menu.append(newitem) newitem = Gtk.MenuItem.new_with_mnemonic(_('_Manage Bookmarks…')) newitem.connect('activate', gajim.interface.roster.on_manage_bookmarks_menuitem_activate) gc_sub_menu.append(newitem) if connected_accounts_with_private_storage == 0: newitem.set_sensitive(False) sounds_mute_menuitem.set_active(not gajim.config.get('sounds_on')) win = gajim.interface.roster.window if self.show_roster_handler_id: show_roster_menuitem.handler_disconnect(self.show_roster_handler_id) if win.get_property('has-toplevel-focus'): show_roster_menuitem.get_children()[0].set_label(_('Hide _Roster')) self.show_roster_handler_id = show_roster_menuitem.connect( 'activate', self.on_hide_roster_menuitem_activate) else: show_roster_menuitem.get_children()[0].set_label(_('Show _Roster')) self.show_roster_handler_id = show_roster_menuitem.connect( 'activate', self.on_show_roster_menuitem_activate) if os.name == 'nt': if self.added_hide_menuitem is False: self.systray_context_menu.prepend(Gtk.SeparatorMenuItem.new()) item = Gtk.MenuItem.new_with_label( _('Hide this menu')) self.systray_context_menu.prepend(item) self.added_hide_menuitem = True self.systray_context_menu.show_all() self.systray_context_menu.popup(None, None, None, None, 0, event_time)
def get_transport_menu(contact, account): roster = gajim.interface.roster jid = contact.jid menu = gtk.Menu() # Send single message item = gtk.ImageMenuItem(_('Send Single _Message...')) icon = gtk.image_new_from_stock(gtk.STOCK_NEW, gtk.ICON_SIZE_MENU) item.set_image(icon) item.connect('activate', roster.on_send_single_message_menuitem_activate, account, contact) menu.append(item) if gajim.account_is_disconnected(account): item.set_sensitive(False) blocked = False if helpers.jid_is_blocked(account, jid): blocked = True # Send Custom Status send_custom_status_menuitem = gtk.ImageMenuItem(_('Send Cus_tom Status')) # add a special img for this menuitem if blocked: send_custom_status_menuitem.set_image(gtkgui_helpers.load_icon( 'offline')) send_custom_status_menuitem.set_sensitive(False) else: if account in gajim.interface.status_sent_to_users and \ jid in gajim.interface.status_sent_to_users[account]: send_custom_status_menuitem.set_image(gtkgui_helpers.load_icon( gajim.interface.status_sent_to_users[account][jid])) else: icon = gtk.image_new_from_stock(gtk.STOCK_NETWORK, gtk.ICON_SIZE_MENU) send_custom_status_menuitem.set_image(icon) status_menuitems = gtk.Menu() send_custom_status_menuitem.set_submenu(status_menuitems) iconset = gajim.config.get('iconset') path = os.path.join(helpers.get_iconset_path(iconset), '16x16') for s in ('online', 'chat', 'away', 'xa', 'dnd', 'offline'): # icon MUST be different instance for every item state_images = gtkgui_helpers.load_iconset(path) status_menuitem = gtk.ImageMenuItem(helpers.get_uf_show(s)) status_menuitem.connect('activate', roster.on_send_custom_status, [(contact, account)], s) icon = state_images[s] status_menuitem.set_image(icon) status_menuitems.append(status_menuitem) menu.append(send_custom_status_menuitem) if gajim.account_is_disconnected(account): send_custom_status_menuitem.set_sensitive(False) item = gtk.SeparatorMenuItem() # separator menu.append(item) # Execute Command item = gtk.ImageMenuItem(_('E_xecute Command...')) icon = gtk.image_new_from_stock(gtk.STOCK_EXECUTE, gtk.ICON_SIZE_MENU) item.set_image(icon) menu.append(item) item.connect('activate', roster.on_execute_command, contact, account, contact.resource) if gajim.account_is_disconnected(account): item.set_sensitive(False) # Manage Transport submenu item = gtk.ImageMenuItem(_('_Manage Transport')) icon = gtk.image_new_from_stock(gtk.STOCK_PROPERTIES, gtk.ICON_SIZE_MENU) item.set_image(icon) manage_transport_submenu = gtk.Menu() item.set_submenu(manage_transport_submenu) menu.append(item) # Modify Transport item = gtk.ImageMenuItem(_('_Modify Transport')) icon = gtk.image_new_from_stock(gtk.STOCK_PREFERENCES, gtk.ICON_SIZE_MENU) item.set_image(icon) manage_transport_submenu.append(item) item.connect('activate', roster.on_edit_agent, contact, account) if gajim.account_is_disconnected(account): item.set_sensitive(False) # Rename item = gtk.ImageMenuItem(_('_Rename...')) # add a special img for rename menuitem gtkgui_helpers.add_image_to_menuitem(item, 'gajim-kbd_input') manage_transport_submenu.append(item) item.connect('activate', roster.on_rename, 'agent', jid, account) if gajim.account_is_disconnected(account): item.set_sensitive(False) item = gtk.SeparatorMenuItem() # separator manage_transport_submenu.append(item) # Block if blocked: item = gtk.ImageMenuItem(_('_Unblock')) item.connect('activate', roster.on_unblock, [(contact, account)]) else: item = gtk.ImageMenuItem(_('_Block')) item.connect('activate', roster.on_block, [(contact, account)]) icon = gtk.image_new_from_stock(gtk.STOCK_STOP, gtk.ICON_SIZE_MENU) item.set_image(icon) manage_transport_submenu.append(item) if gajim.account_is_disconnected(account): item.set_sensitive(False) # Remove item = gtk.ImageMenuItem(_('Remo_ve')) icon = gtk.image_new_from_stock(gtk.STOCK_REMOVE, gtk.ICON_SIZE_MENU) item.set_image(icon) manage_transport_submenu.append(item) item.connect('activate', roster.on_remove_agent, [(contact, account)]) if gajim.account_is_disconnected(account): item.set_sensitive(False) item = gtk.SeparatorMenuItem() # separator menu.append(item) # Information information_menuitem = gtk.ImageMenuItem(_('_Information')) icon = gtk.image_new_from_stock(gtk.STOCK_INFO, gtk.ICON_SIZE_MENU) information_menuitem.set_image(icon) menu.append(information_menuitem) information_menuitem.connect('activate', roster.on_info, contact, account) if gajim.account_is_disconnected(account): information_menuitem.set_sensitive(False) menu.connect('selection-done', gtkgui_helpers.destroy_widget) menu.show_all() return menu
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
def fill_jabber_page(self): tooltips = gtk.Tooltips() self.xml.get_widget('nickname_label').set_text(self.contact.name) self.xml.get_widget('jid_label').set_text(self.contact.jid) uf_sub = helpers.get_uf_sub(self.contact.sub) self.xml.get_widget('subscription_label').set_text(uf_sub) eb = self.xml.get_widget('subscription_label_eventbox') if self.contact.sub == 'from': tt_text = _("This contact is interested in your presence information, but you are not interested in his/her presence") elif self.contact.sub == 'to': tt_text = _("You are interested in the contact's presence information, but he/she is not interested in yours") elif self.contact.sub == 'both': tt_text = _("You and the contact are interested in each other's presence information") else: # None tt_text = _("You are not interested in the contact's presence, and neither he/she is interested in yours") tooltips.set_tip(eb, tt_text) label = self.xml.get_widget('ask_label') uf_ask = helpers.get_uf_ask(self.contact.ask) label.set_text(uf_ask) eb = self.xml.get_widget('ask_label_eventbox') if self.contact.ask == 'subscribe': tooltips.set_tip(eb, _("You are waiting contact's answer about your subscription request")) self.xml.get_widget('nickname_entry').set_text(self.contact.name) log = True if self.contact.jid in gajim.config.get_per('accounts', self.account, 'no_log_for').split(' '): log = False checkbutton = self.xml.get_widget('log_history_checkbutton') checkbutton.set_active(log) checkbutton.connect('toggled', self.on_log_history_checkbutton_toggled) resources = '%s (%s)' % (self.contact.resource, unicode( self.contact.priority)) uf_resources = self.contact.resource + _(' resource with priority ')\ + unicode(self.contact.priority) if not self.contact.status: self.contact.status = '' # stats holds show and status message stats = helpers.get_uf_show(self.contact.show) if self.contact.status: stats += ': ' + self.contact.status gajim.connections[self.account].request_os_info(self.contact.jid, self.contact.resource) self.os_info = {0: {'resource': self.contact.resource, 'client': '', 'os': ''}} i = 1 if gajim.contacts[self.account].has_key(self.contact.jid): for c in gajim.contacts[self.account][self.contact.jid]: if c.resource != self.contact.resource: resources += '\n%s (%s)' % (c.resource, unicode(c.priority)) uf_resources += '\n' + c.resource + _(' resource with priority ')\ + unicode(c.priority) if not c.status: c.status = '' stats += '\n' + c.show + ': ' + c.status gajim.connections[self.account].request_os_info(self.contact.jid, c.resource) self.os_info[i] = {'resource': c.resource, 'client': '', 'os': ''} i += 1 self.xml.get_widget('resource_prio_label').set_text(resources) tip = gtk.Tooltips() resource_prio_label_eventbox = self.xml.get_widget( 'resource_prio_label_eventbox') tip.set_tip(resource_prio_label_eventbox, uf_resources) tip = gtk.Tooltips() status_label_eventbox = self.xml.get_widget('status_label_eventbox') tip.set_tip(status_label_eventbox, stats) status_label = self.xml.get_widget('status_label') status_label.set_max_width_chars(15) status_label.set_text(stats) gajim.connections[self.account].request_vcard(self.contact.jid)
def _add_new_line(self, contact_name, tim, kind, show, message, subject, additional_data): """ Add a new line in textbuffer """ if not message and kind not in (constants.KIND_STATUS, constants.KIND_GCSTATUS): return buf = self.history_buffer end_iter = buf.get_end_iter() if gajim.config.get('print_time') == 'always': timestamp_str = gajim.config.get('time_stamp') timestamp_str = helpers.from_one_line(timestamp_str) tim = time.strftime(timestamp_str, time.localtime(float(tim))) buf.insert(end_iter, tim) # add time elif gajim.config.get('print_time') == 'sometimes': every_foo_seconds = 60 * gajim.config.get( 'print_ichat_every_foo_minutes') seconds_passed = tim - self.last_time_printout if seconds_passed > every_foo_seconds: self.last_time_printout = tim tim = time.strftime('%X ', time.localtime(float(tim))) buf.insert_with_tags_by_name(end_iter, tim + '\n', 'time_sometimes') else: # don't print time. So we print it as invisible to be able to # search for it timestamp_str = gajim.config.get('time_stamp') timestamp_str = helpers.from_one_line(timestamp_str) tim = time.strftime(timestamp_str, time.localtime(float(tim))) buf.insert_with_tags_by_name(end_iter, tim, 'invisible') tag_name = '' tag_msg = '' show = self._get_string_show_from_constant_int(show) if kind == constants.KIND_GC_MSG: tag_name = 'incoming' elif kind in (constants.KIND_SINGLE_MSG_RECV, constants.KIND_CHAT_MSG_RECV): contact_name = self.completion_dict[self.jid][C_INFO_NAME] tag_name = 'incoming' tag_msg = 'incomingtxt' elif kind in (constants.KIND_SINGLE_MSG_SENT, constants.KIND_CHAT_MSG_SENT): if self.account: contact_name = gajim.nicks[self.account] else: # we don't have roster, we don't know our own nick, use first # account one (urk!) account = list(gajim.contacts.get_accounts())[0] contact_name = gajim.nicks[account] tag_name = 'outgoing' tag_msg = 'outgoingtxt' elif kind == constants.KIND_GCSTATUS: # message here (if not None) is status message if message: message = _('%(nick)s is now %(status)s: %(status_msg)s') %\ {'nick': contact_name, 'status': helpers.get_uf_show(show), 'status_msg': message } else: message = _('%(nick)s is now %(status)s') % {'nick': contact_name, 'status': helpers.get_uf_show(show) } tag_msg = 'status' else: # 'status' # message here (if not None) is status message if show is None: # it means error if message: message = _('Error: %s') % message else: message = _('Error') elif message: message = _('Status is now: %(status)s: %(status_msg)s') % \ {'status': helpers.get_uf_show(show), 'status_msg': message} else: message = _('Status is now: %(status)s') % { 'status': helpers.get_uf_show(show) } tag_msg = 'status' if message.startswith('/me ') or message.startswith('/me\n'): tag_msg = tag_name else: # do not do this if gcstats, avoid dupping contact_name # eg. nkour: nkour is now Offline if contact_name and kind != constants.KIND_GCSTATUS: # add stuff before and after contact name before_str = gajim.config.get('before_nickname') before_str = helpers.from_one_line(before_str) after_str = gajim.config.get('after_nickname') after_str = helpers.from_one_line(after_str) format = before_str + contact_name + after_str + ' ' if tag_name: buf.insert_with_tags_by_name(end_iter, format, tag_name) else: buf.insert(end_iter, format) if subject: message = _('Subject: %s\n') % subject + message xhtml = None if message.startswith('<body '): xhtml = message if tag_msg: self.history_textview.print_real_text(message, [tag_msg], name=contact_name, xhtml=xhtml, additional_data=additional_data) else: self.history_textview.print_real_text(message, name=contact_name, xhtml=xhtml, additional_data=additional_data) buffer_ = self.history_textview.tv.get_buffer() eob = buffer_.get_end_iter() buffer_.insert_with_tags_by_name(eob, '\n', 'eol')
def get_transport_menu(contact, account): roster = gajim.interface.roster jid = contact.jid menu = Gtk.Menu() # Send single message item = Gtk.MenuItem.new_with_mnemonic(_('Send Single _Message...')) item.connect('activate', roster.on_send_single_message_menuitem_activate, account, contact) menu.append(item) if gajim.account_is_disconnected(account): item.set_sensitive(False) blocked = False if helpers.jid_is_blocked(account, jid): blocked = True # Send Custom Status send_custom_status_menuitem = Gtk.MenuItem.new_with_mnemonic( _('Send Cus_tom Status')) if blocked: send_custom_status_menuitem.set_sensitive(False) else: status_menuitems = Gtk.Menu() send_custom_status_menuitem.set_submenu(status_menuitems) for s in ('online', 'chat', 'away', 'xa', 'dnd', 'offline'): status_menuitem = Gtk.MenuItem.new_with_label(helpers.get_uf_show( s)) status_menuitem.connect('activate', roster.on_send_custom_status, [(contact, account)], s) status_menuitems.append(status_menuitem) menu.append(send_custom_status_menuitem) if gajim.account_is_disconnected(account): send_custom_status_menuitem.set_sensitive(False) item = Gtk.SeparatorMenuItem.new() # separator menu.append(item) # Execute Command item = Gtk.MenuItem.new_with_mnemonic(_('E_xecute Command...')) menu.append(item) item.connect('activate', roster.on_execute_command, contact, account, contact.resource) if gajim.account_is_disconnected(account): item.set_sensitive(False) # Manage Transport submenu item = Gtk.MenuItem.new_with_mnemonic(_('_Manage Transport')) manage_transport_submenu = Gtk.Menu() item.set_submenu(manage_transport_submenu) menu.append(item) # Modify Transport item = Gtk.MenuItem.new_with_mnemonic(_('_Modify Transport')) manage_transport_submenu.append(item) item.connect('activate', roster.on_edit_agent, contact, account) if gajim.account_is_disconnected(account): item.set_sensitive(False) # Rename item = Gtk.MenuItem.new_with_mnemonic(_('_Rename...')) manage_transport_submenu.append(item) item.connect('activate', roster.on_rename, 'agent', jid, account) if gajim.account_is_disconnected(account): item.set_sensitive(False) item = Gtk.SeparatorMenuItem.new() # separator manage_transport_submenu.append(item) # Block if blocked: item = Gtk.MenuItem.new_with_mnemonic(_('_Unblock')) item.connect('activate', roster.on_unblock, [(contact, account)]) else: item = Gtk.MenuItem.new_with_mnemonic(_('_Block')) item.connect('activate', roster.on_block, [(contact, account)]) manage_transport_submenu.append(item) if gajim.account_is_disconnected(account): item.set_sensitive(False) # Remove item = Gtk.MenuItem.new_with_mnemonic(_('Remo_ve')) manage_transport_submenu.append(item) item.connect('activate', roster.on_remove_agent, [(contact, account)]) if gajim.account_is_disconnected(account): item.set_sensitive(False) item = Gtk.SeparatorMenuItem.new() # separator menu.append(item) # Information information_menuitem = Gtk.MenuItem.new_with_mnemonic(_('_Information')) menu.append(information_menuitem) information_menuitem.connect('activate', roster.on_info, contact, account) if gajim.account_is_disconnected(account): information_menuitem.set_sensitive(False) menu.connect('selection-done', gtkgui_helpers.destroy_widget) menu.show_all() return menu
def make_menu(self, event_button, event_time): '''create chat with and new message (sub) menus/menuitems''' for m in self.popup_menus: m.destroy() chat_with_menuitem = self.xml.get_widget('chat_with_menuitem') single_message_menuitem = self.xml.get_widget( 'single_message_menuitem') status_menuitem = self.xml.get_widget('status_menu') join_gc_menuitem = self.xml.get_widget('join_gc_menuitem') sounds_mute_menuitem = self.xml.get_widget('sounds_mute_menuitem') if self.single_message_handler_id: single_message_menuitem.handler_disconnect( self.single_message_handler_id) self.single_message_handler_id = None if self.new_chat_handler_id: chat_with_menuitem.disconnect(self.new_chat_handler_id) self.new_chat_handler_id = None sub_menu = gtk.Menu() self.popup_menus.append(sub_menu) status_menuitem.set_submenu(sub_menu) gc_sub_menu = gtk.Menu() # gc is always a submenu join_gc_menuitem.set_submenu(gc_sub_menu) # We need our own set of status icons, let's make 'em! iconset = gajim.config.get('iconset') path = os.path.join(helpers.get_iconset_path(iconset), '16x16') state_images = gtkgui_helpers.load_iconset(path) if 'muc_active' in state_images: join_gc_menuitem.set_image(state_images['muc_active']) for show in ('online', 'chat', 'away', 'xa', 'dnd', 'invisible'): uf_show = helpers.get_uf_show(show, use_mnemonic = True) item = gtk.ImageMenuItem(uf_show) item.set_image(state_images[show]) sub_menu.append(item) if os.name == 'nt': #FIXME: bug in pygtk, activate is not called. # see http://trac.gajim.org/ticket/4310 item.connect('button_press_event', self.on_show_menuitem_activate2, show) else: item.connect('activate', self.on_show_menuitem_activate, show) item = gtk.SeparatorMenuItem() sub_menu.append(item) item = gtk.ImageMenuItem(_('_Change Status Message...')) path = os.path.join(gajim.DATA_DIR, 'pixmaps', 'kbd_input.png') img = gtk.Image() img.set_from_file(path) item.set_image(img) sub_menu.append(item) if os.name == 'nt': #FIXME: bug in pygtk, activate is not called. # see http://trac.gajim.org/ticket/4310 item.connect('button_press_event', self.on_change_status_message_activate2) else: item.connect('activate', self.on_change_status_message_activate) connected_accounts = gajim.get_number_of_connected_accounts() if connected_accounts < 1: item.set_sensitive(False) item = gtk.SeparatorMenuItem() sub_menu.append(item) uf_show = helpers.get_uf_show('offline', use_mnemonic = True) item = gtk.ImageMenuItem(uf_show) item.set_image(state_images['offline']) sub_menu.append(item) if os.name == 'nt': #FIXME: bug in pygtk, activate is not called. # see http://trac.gajim.org/ticket/4310 item.connect('button_press_event', self.on_show_menuitem_activate2, 'offline') else: item.connect('activate', self.on_show_menuitem_activate, 'offline') iskey = connected_accounts > 0 and not (connected_accounts == 1 and gajim.connections[gajim.connections.keys()[0]].is_zeroconf) chat_with_menuitem.set_sensitive(iskey) single_message_menuitem.set_sensitive(iskey) join_gc_menuitem.set_sensitive(iskey) if connected_accounts >= 2: # 2 or more connections? make submenus account_menu_for_chat_with = gtk.Menu() chat_with_menuitem.set_submenu(account_menu_for_chat_with) self.popup_menus.append(account_menu_for_chat_with) account_menu_for_single_message = gtk.Menu() single_message_menuitem.set_submenu( account_menu_for_single_message) self.popup_menus.append(account_menu_for_single_message) accounts_list = sorted(gajim.contacts.get_accounts()) for account in accounts_list: if gajim.connections[account].is_zeroconf: continue if gajim.connections[account].connected > 1: # for chat_with item = gtk.MenuItem(_('using account %s') % account) account_menu_for_chat_with.append(item) if os.name == 'nt': #FIXME: bug in pygtk, activate is not called. # see http://trac.gajim.org/ticket/4310 item.connect('button_press_event', self.on_new_chat2, account) else: item.connect('activate', self.on_new_chat, account) # for single message item = gtk.MenuItem(_('using account %s') % account) if os.name == 'nt': #FIXME: bug in pygtk, activate is not called. # see http://trac.gajim.org/ticket/4310 item.connect('button_press_event', self.on_single_message_menuitem_activate2, account) else: item.connect('activate', self.on_single_message_menuitem_activate, account) account_menu_for_single_message.append(item) # join gc gc_item = gtk.MenuItem(_('using account %s') % account, False) gc_sub_menu.append(gc_item) gc_menuitem_menu = gtk.Menu() if os.name == 'nt': #FIXME: bug in pygtk, activate is not called. # see http://trac.gajim.org/ticket/4310 self.add_bookmarks_list2(gc_menuitem_menu, account) else: gajim.interface.roster.add_bookmarks_list(gc_menuitem_menu, account) gc_item.set_submenu(gc_menuitem_menu) gc_sub_menu.show_all() elif connected_accounts == 1: # one account # one account connected, no need to show 'as jid' for account in gajim.connections: if gajim.connections[account].connected > 1: self.new_chat_handler_id = chat_with_menuitem.connect( 'activate', self.on_new_chat, account) # for single message single_message_menuitem.remove_submenu() self.single_message_handler_id = single_message_menuitem.\ connect('activate', self.on_single_message_menuitem_activate, account) # join gc if os.name == 'nt': #FIXME: bug in pygtk, activate is not called. # see http://trac.gajim.org/ticket/4310 self.add_bookmarks_list2(gc_sub_menu, account) else: gajim.interface.roster.add_bookmarks_list(gc_sub_menu, account) break # No other connected account newitem = gtk.SeparatorMenuItem() # separator gc_sub_menu.append(newitem) newitem = gtk.ImageMenuItem(_('_Manage Bookmarks...')) img = gtk.image_new_from_stock(gtk.STOCK_PREFERENCES, gtk.ICON_SIZE_MENU) newitem.set_image(img) if os.name == 'nt': #FIXME: bug in pygtk, activate is not called. # see http://trac.gajim.org/ticket/4310 newitem.connect('button_press_event', self.on_manage_bookmarks_menuitem_activate2) else: newitem.connect('activate', gajim.interface.roster.on_manage_bookmarks_menuitem_activate) gc_sub_menu.append(newitem) sounds_mute_menuitem.set_active(not gajim.config.get('sounds_on')) if os.name == 'nt': if gtk.pygtk_version >= (2, 10, 0) and gtk.gtk_version >= (2, 10, 0): if self.added_hide_menuitem is False: self.systray_context_menu.prepend(gtk.SeparatorMenuItem()) item = gtk.MenuItem(_('Hide this menu')) self.systray_context_menu.prepend(item) self.added_hide_menuitem = True self.systray_context_menu.show_all() self.systray_context_menu.popup(None, None, None, event_button, event_time)