def get_tab_image(self, count_unread=True): jid = self.gc_contact.get_full_jid() if app.config.get('show_avatar_in_tabs'): scale = self.parent_win.window.get_scale_factor() surface = app.contacts.get_avatar( self.account, jid, AvatarSize.TAB, scale) if surface is not None: return surface if count_unread: num_unread = len(app.events.get_events( self.account, jid, ['printed_' + self.type_id, self.type_id])) else: num_unread = 0 transport = None if app.jid_is_transport(jid): transport = app.get_transport_name_from_jid(jid) if self.gc_contact.presence.is_unavailable: show = 'offline' else: show = self.gc_contact.show.value if num_unread and app.config.get('show_unread_tab_icon'): icon_name = get_icon_name('event', transport=transport) else: icon_name = get_icon_name(show, transport=transport) return icon_name
def _update_banner_state_image(self): # Set banner image if self.gc_contact.presence.is_unavailable: icon = get_icon_name('offline') else: icon = get_icon_name(self.gc_contact.show.value) banner_status_img = self.xml.get_object('banner_status_image') banner_status_img.set_from_icon_name(icon, Gtk.IconSize.DND)
def show_icon(self): window_mode = app.interface.msg_win_mgr.mode if window_mode in (MessageWindowMgr.ONE_MSG_WINDOW_PERTYPE, MessageWindowMgr.ONE_MSG_WINDOW_NEVER): if self.type_ == 'gc': icon = get_icon_name('muc-active') self.window.set_icon_name(icon)
def add_status_row(self, show, str_status, show_lock=False, indent=True, transport=None): """ Append a new row with status icon to the table """ self.table.insert_row(self.current_row) image = Gtk.Image() icon_name = get_icon_name(show, transport=transport) image.set_from_icon_name(icon_name, Gtk.IconSize.MENU) spacer = Gtk.Label(label=self.spacer_label) image.set_halign(Gtk.Align.START) image.set_valign(Gtk.Align.CENTER) if indent: self.table.attach(spacer, 1, self.current_row, 1, 1) self.table.attach(image, 2, self.current_row, 1, 1) status_label = Gtk.Label() status_label.set_markup(str_status) status_label.set_halign(Gtk.Align.START) status_label.set_valign(Gtk.Align.START) status_label.set_line_wrap(True) self.table.attach(status_label, 3, self.current_row, 1, 1) if show_lock: lock_image = Gtk.Image() lock_image.set_from_icon_name('dialog-password', Gtk.IconSize.MENU) self.table.attach(lock_image, 4, self.current_row, 1, 1) self.current_row += 1
def _get_icon_name(obj): if obj.notif_type == 'msg': if obj.base_event.properties.is_muc_pm: return 'gajim-priv_msg_recv' elif obj.notif_type == 'pres': if obj.transport_name is not None: return '%s-%s' % (obj.transport_name, obj.show) return get_icon_name(obj.show) return None
def _get_icon_name(obj): if obj.notif_type == 'msg': if obj.base_event.mtype == 'pm': return 'gajim-priv_msg_recv' if obj.base_event.mtype == 'normal': return 'gajim-single_msg_recv' elif obj.notif_type == 'pres': if obj.transport_name is not None: return '%s-%s' % (obj.transport_name, obj.show) return get_icon_name(obj.show)
def set_img(self, *args): """ Apart from image, we also update tooltip text here """ if not app.interface.systray_enabled: return if app.config.get('trayicon') == 'always': self.status_icon.set_visible(True) if app.events.get_nb_systray_events(): self.status_icon.set_visible(True) icon_name = get_icon_name('event') self.status_icon.set_from_icon_name(icon_name) return if app.config.get('trayicon') == 'on_event': self.status_icon.set_visible(False) icon_name = get_icon_name(self.status) self.status_icon.set_from_icon_name(icon_name)
def _get_avatar_image(self, account, jid, show): if self.new: icon_name = 'avatar-default' if self.groupchat: icon_name = get_icon_name('muc-inactive') return Gtk.Image.new_from_icon_name(icon_name, Gtk.IconSize.DND) scale = self.get_scale_factor() if self.groupchat: surface = app.interface.avatar_storage.get_muc_surface( account, jid, AvatarSize.CHAT, scale) return Gtk.Image.new_from_surface(surface) avatar = app.contacts.get_avatar(account, jid, AvatarSize.CHAT, scale, show) return Gtk.Image.new_from_surface(avatar)
def __init__(self, account, to='', action='', from_whom='', subject='', message='', resource='', session=None, form_node=None): Gtk.ApplicationWindow.__init__(self) self.set_application(app.app) self.set_title(_('Send Single Message')) self.set_name('SendSingleMessageWindow') self.account = account self.action = action self.subject = subject self.message = message self.to = to self.from_whom = from_whom self.resource = resource self.session = session self._ui = get_builder('single_message_window.ui') self.message_tv_buffer = self._ui.message_textview.get_buffer() self.conversation_textview = ConversationTextview( account, used_in_history_window=True) self.conversation_textview.tv.show() self.conversation_textview.tv.set_left_margin(6) self.conversation_textview.tv.set_right_margin(6) self.conversation_textview.tv.set_top_margin(6) self.conversation_textview.tv.set_bottom_margin(6) self.conversation_tv_buffer = self.conversation_textview.tv.get_buffer( ) self._ui.conversation_scrolledwindow.add(self.conversation_textview.tv) self.form_widget = None parent_box = self._ui.conversation_scrolledwindow.get_parent() if form_node: self.form_widget = DataFormWidget(form_node) self.form_widget.show_all() self._ui.conversation_scrolledwindow.hide() self._ui.message_label_received.hide() parent_box.add(self.form_widget) parent_box.child_set_property(self.form_widget, 'top-attach', 2) parent_box.child_set_property(self.form_widget, 'left-attach', 0) parent_box.child_set_property(self.form_widget, 'width', 2) self.action = 'form' self.message_tv_buffer.connect('changed', self.update_char_counter) if isinstance(to, list): jid = ', '.join([i[0].get_full_jid() for i in to]) self._ui.to_entry.set_text(jid) else: self._ui.to_entry.set_text(to) if app.config.get('use_speller') and app.is_installed( 'GSPELL') and action == 'send': lang = app.config.get('speller_language') gspell_lang = Gspell.language_lookup(lang) if gspell_lang is None: AspellDictError(lang) else: spell_buffer = Gspell.TextBuffer.get_from_gtk_text_buffer( self._ui.message_textview.get_buffer()) spell_buffer.set_spell_checker(Gspell.Checker.new(gspell_lang)) spell_view = Gspell.TextView.get_from_gtk_text_view( self._ui.message_textview) spell_view.set_inline_spell_checking(True) spell_view.set_enable_language_menu(True) self.prepare_widgets_for(self.action) # set_text(None) raises TypeError exception if self.subject is None: self.subject = _('(No subject)') self._ui.subject_entry.set_text(self.subject) self._ui.subject_from_entry_label.set_text(self.subject) if to == '': liststore = get_completion_liststore(self._ui.to_entry) self.completion_dict = helpers.get_contact_dict_for_account( account) keys = sorted(self.completion_dict.keys()) for jid in keys: contact = self.completion_dict[jid] status_icon = get_icon_name(contact.show) liststore.append((status_icon, jid)) else: self.completion_dict = {} self._ui.to_entry.connect('changed', self.on_to_entry_changed) self._ui.connect_signals(self) # get window position and size from config resize_window(self._ui.single_message_window, app.config.get('single-msg-width'), app.config.get('single-msg-height')) move_window(self._ui.single_message_window, app.config.get('single-msg-x-position'), app.config.get('single-msg-y-position')) self._ui.single_message_window.show_all()
def _fill_completion_dict(self): """ Fill completion_dict for key auto completion. Then load history for current jid (by calling another function) Key will be either jid or full_completion_name (contact name or long description like "pm-contact from groupchat...."). {key : (jid, account, nick_name, full_completion_name} This is a generator and does pseudo-threading via idle_add(). """ liststore = get_completion_liststore( self._ui.query_entry.get_child()) liststore.set_sort_column_id(1, Gtk.SortType.ASCENDING) self._ui.query_entry.get_child().get_completion().connect( 'match-selected', self.on_jid_entry_match_selected) self._ui.query_entry.set_model(liststore) # Add all jids in logs.db: db_jids = app.logger.get_jids_in_db() completion_dict = dict.fromkeys(db_jids) self.accounts_seen_online = list(app.contacts.get_accounts()) # Enhance contacts of online accounts with contact. # Needed for mapping below for account in self.accounts_seen_online: completion_dict.update( helpers.get_contact_dict_for_account(account)) muc_active_icon = get_icon_name('muc-active') online_icon = get_icon_name('online') keys = list(completion_dict.keys()) # Move the actual jid at first so we load history faster actual_jid = self._ui.query_entry.get_child().get_text() if actual_jid in keys: keys.remove(actual_jid) keys.insert(0, actual_jid) if '' in keys: keys.remove('') if None in keys: keys.remove(None) # Map jid to info tuple # Warning : This for is time critical with big DB for key in keys: completed = key completed2 = None contact = completion_dict[completed] if contact: info_name = contact.get_shown_name() info_completion = info_name info_jid = contact.jid else: # Corresponding account is offline, we know nothing info_name = completed.split('@')[0] info_completion = completed info_jid = completed info_acc = self._get_account_for_jid(info_jid) if (app.logger.jid_is_room_jid(completed) or app.logger.jid_is_from_pm(completed)): icon = muc_active_icon if app.logger.jid_is_from_pm(completed): # It's PM. Make it easier to find room, nick = app.get_room_and_nick_from_fjid(completed) info_completion = '%s from %s' % (nick, room) completed = info_completion info_completion2 = '%s/%s' % (room, nick) completed2 = info_completion2 info_name = nick else: icon = online_icon if len(completed) > 70: completed = completed[:70] + '[\u2026]' liststore.append((icon, completed)) self.completion_dict[key] = ( info_jid, info_acc, info_name, info_completion) self.completion_dict[completed] = ( info_jid, info_acc, info_name, info_completion) if completed2: if len(completed2) > 70: completed2 = completed2[:70] + '[\u2026]' liststore.append((icon, completed2)) self.completion_dict[completed2] = ( info_jid, info_acc, info_name, info_completion2) if key == actual_jid: self._load_history(info_jid, self.account or info_acc) yield True keys.sort() yield False
def __init__(self): Gtk.ApplicationWindow.__init__(self) self.set_application(app.app) self.set_position(Gtk.WindowPosition.CENTER) self.set_show_menubar(False) self.set_title(_('Preferences')) self._ui = get_builder('preferences_window.ui') self.add(self._ui.preferences_window) ### General tab ### ## Behavior of Windows and Tabs # Set default for single window type choices = c_config.opt_one_window_types type_ = app.config.get('one_message_window') if type_ in choices: self._ui.one_window_type_combobox.set_active(choices.index(type_)) else: self._ui.one_window_type_combobox.set_active(0) # Show roster on startup choices = c_config.opt_show_roster_on_startup type_ = app.config.get('show_roster_on_startup') if type_ in choices: self._ui.show_roster_on_startup.set_active(choices.index(type_)) else: self._ui.show_roster_on_startup.set_active(0) # Quit on roster x st = app.config.get('quit_on_roster_x_button') self._ui.quit_on_roster_x_checkbutton.set_active(st) # Tab placement st = app.config.get('tabs_position') if st == 'top': self._ui.tabs_placement.set_active(0) elif st == 'bottom': self._ui.tabs_placement.set_active(1) elif st == 'left': self._ui.tabs_placement.set_active(2) else: # right self._ui.tabs_placement.set_active(3) # Show avatar in tabs st = app.config.get('show_avatar_in_tabs') self._ui.show_avatar_in_tabs_checkbutton.set_active(st) ## Contact List Appearance # Display avatars in roster st = app.config.get('show_avatars_in_roster') self._ui.show_avatars_in_roster_checkbutton.set_active(st) # Display status msg under contact name in roster st = app.config.get('show_status_msgs_in_roster') self._ui.show_status_msgs_in_roster_checkbutton.set_active(st) # Display PEP in roster st1 = app.config.get('show_mood_in_roster') st2 = app.config.get('show_activity_in_roster') st3 = app.config.get('show_tunes_in_roster') st4 = app.config.get('show_location_in_roster') if st1 == st2 == st3 == st4: self._ui.show_pep_in_roster_checkbutton.set_active(st1) else: self._ui.show_pep_in_roster_checkbutton.set_inconsistent(True) # Sort contacts by show st = app.config.get('sort_by_show_in_roster') self._ui.sort_by_show_in_roster_checkbutton.set_active(st) st = app.config.get('sort_by_show_in_muc') self._ui.sort_by_show_in_muc_checkbutton.set_active(st) ### Chat tab ### ## Chat Settings # Use speller if app.is_installed('GSPELL'): st = app.config.get('use_speller') self._ui.speller_checkbutton.set_active(st) else: self._ui.speller_checkbutton.set_sensitive(False) # XEP-0184 positive ack st = app.config.get('positive_184_ack') self._ui.positive_184_ack_checkbutton.set_active(st) # Ignore XHTML st = app.config.get('ignore_incoming_xhtml') self._ui.xhtml_checkbutton.set_active(st) # Print status messages in single chats st = app.config.get('print_status_in_chats') self._ui.print_status_in_chats_checkbutton.set_active(st) # Show subject on join st = app.config.get('show_subject_on_join') self._ui.subject_on_join_checkbutton.set_active(st) # Group chat settings threshold_model = self._ui.sync_threshold_combobox.get_model() days = app.config.get_options('threshold_options', return_type=int) for day in days: if day == 0: label = _('No threshold') else: label = ngettext('%i day', '%i days', day, day, day) threshold_model.append([str(day), label]) public_threshold = app.config.get('public_room_sync_threshold') self._ui.sync_threshold_combobox.set_id_column(0) self._ui.sync_threshold_combobox.set_active_id(str(public_threshold)) st = app.config.get('print_join_left_default') self._ui.join_leave_checkbutton.set_active(st) st = app.config.get('print_status_muc_default') self._ui.status_change_checkbutton.set_active(st) # Displayed chat state notifications st = app.config.get('show_chatstate_in_tabs') self._ui.show_chatstate_in_tabs.set_active(st) st = app.config.get('show_chatstate_in_roster') self._ui.show_chatstate_in_roster.set_active(st) st = app.config.get('show_chatstate_in_banner') self._ui.show_chatstate_in_banner.set_active(st) ### Notifications tab ### ## Visual Notifications # Systray icon if app.config.get('trayicon') == 'never': self._ui.systray_combobox.set_active(0) elif app.config.get('trayicon') == 'on_event': self._ui.systray_combobox.set_active(1) else: # always self._ui.systray_combobox.set_active(2) # Notify on new event if app.config.get('autopopup'): self._ui.on_event_received_combobox.set_active(0) elif app.config.get('notify_on_new_message'): self._ui.on_event_received_combobox.set_active(1) else: # only show in roster self._ui.on_event_received_combobox.set_active(2) # Notify on online statuses st = app.config.get('notify_on_signin') self._ui.notify_on_signin_checkbutton.set_active(st) # Notify on offline statuses st = app.config.get('notify_on_signout') self._ui.notify_on_signout_checkbutton.set_active(st) # Auto popup when away st = app.config.get('autopopupaway') self._ui.auto_popup_away_checkbutton.set_active(st) # Auto popup when chat already open st = app.config.get('autopopup_chat_opened') self._ui.auto_popup_chat_opened_checkbutton.set_active(st) ## Sounds # Sounds if app.config.get('sounds_on'): self._ui.play_sounds_checkbutton.set_active(True) else: self._ui.manage_sounds_button.set_sensitive(False) # Allow sounds when dnd st = app.config.get('sounddnd') self._ui.sound_dnd_checkbutton.set_active(st) #### Status tab ### # Auto away st = app.config.get('autoaway') self._ui.auto_away_checkbutton.set_active(st) # Auto away time st = app.config.get('autoawaytime') self._ui.auto_away_time_spinbutton.set_value(st) self._ui.auto_away_time_spinbutton.set_sensitive( app.config.get('autoaway')) # Auto away message st = app.config.get('autoaway_message') self._ui.auto_away_message_entry.set_text(st) self._ui.auto_away_message_entry.set_sensitive( app.config.get('autoaway')) # Auto xa st = app.config.get('autoxa') self._ui.auto_xa_checkbutton.set_active(st) # Auto xa time st = app.config.get('autoxatime') self._ui.auto_xa_time_spinbutton.set_value(st) self._ui.auto_xa_time_spinbutton.set_sensitive( app.config.get('autoxa')) # Auto xa message st = app.config.get('autoxa_message') self._ui.auto_xa_message_entry.set_text(st) self._ui.auto_xa_message_entry.set_sensitive(app.config.get('autoxa')) if not idle.Monitor.is_available(): self._ui.autoaway_table.set_sensitive(False) # Restore last status st = self.get_per_account_option('restore_last_status') if st == 'mixed': self._ui.restore_last_status_checkbutton.set_inconsistent(True) else: self._ui.restore_last_status_checkbutton.set_active(st) # Ask for status when online/offline st = app.config.get('ask_online_status') self._ui.prompt_online_status_message_checkbutton.set_active(st) st = app.config.get('ask_offline_status') self._ui.prompt_offline_status_message_checkbutton.set_active(st) # Default status messages self.fill_default_msg_treeview() # Status messages renderer = Gtk.CellRendererText() renderer.connect('edited', self.on_msg_cell_edited) renderer.set_property('editable', True) col = Gtk.TreeViewColumn('name', renderer, text=0) self._ui.msg_treeview.append_column(col) self.fill_msg_treeview() buf = self._ui.msg_textview.get_buffer() buf.connect('end-user-action', self.on_msg_textview_changed) ### Style tab ### # Themes self.changed_id = self._ui.theme_combobox.connect( 'changed', self.on_theme_combobox_changed) self.update_theme_list() # Dark theme self._ui.dark_theme_combobox.set_active_id( str(app.config.get('dark_theme'))) # Emoticons emoticon_themes = helpers.get_available_emoticon_themes() for theme in emoticon_themes: self._ui.emoticons_combobox.append_text(theme) config_theme = app.config.get('emoticons_theme') if config_theme not in emoticon_themes: config_theme = 'font' self._ui.emoticons_combobox.set_id_column(0) self._ui.emoticons_combobox.set_active_id(config_theme) self._ui.ascii_emoticons.set_active(app.config.get('ascii_emoticons')) # Iconset model = Gtk.ListStore(str, str) renderer_image = Gtk.CellRendererPixbuf() renderer_text = Gtk.CellRendererText() renderer_text.set_property('xpad', 5) self._ui.iconset_combobox.pack_start(renderer_image, False) self._ui.iconset_combobox.pack_start(renderer_text, True) self._ui.iconset_combobox.add_attribute(renderer_text, 'text', 1) self._ui.iconset_combobox.add_attribute(renderer_image, 'icon_name', 0) self._ui.iconset_combobox.set_model(model) for index, iconset_name in enumerate(get_available_iconsets()): icon_name = get_icon_name('online', iconset=iconset_name) model.append([icon_name, iconset_name]) if app.config.get('iconset') == iconset_name: self._ui.iconset_combobox.set_active(index) # Use transports iconsets st = app.config.get('use_transports_iconsets') self._ui.transports_iconsets_checkbutton.set_active(st) ### Audio/Video tab ### def create_av_combobox(opt_name, device_dict, config_name=None, key=None): combobox = self._ui.get_object(opt_name + '_combobox') cell = Gtk.CellRendererText() cell.set_property('ellipsize', Pango.EllipsizeMode.END) cell.set_property('ellipsize-set', True) combobox.pack_start(cell, True) combobox.add_attribute(cell, 'text', 0) model = Gtk.ListStore(str, str) combobox.set_model(model) if config_name: config = app.config.get(config_name) else: config = app.config.get(opt_name + '_device') for index, (name, value) in enumerate( sorted(device_dict.items(), key=key)): model.append((name, value)) if config == value: combobox.set_active(index) if HAS_GST and app.is_installed('FARSTREAM'): create_av_combobox('audio_input', AudioInputManager().get_devices()) create_av_combobox('audio_output', AudioOutputManager().get_devices()) create_av_combobox('video_input', VideoInputManager().get_devices()) create_av_combobox('video_output', VideoOutputManager().get_devices()) create_av_combobox('video_framerate', {_('Default'): '', '15fps': '15/1', '10fps': '10/1', '5fps': '5/1', '2.5fps': '5/2'}, 'video_framerate', key=lambda x: -1 if \ not x[1] else float(x[0][:-3])) create_av_combobox('video_size', {_('Default'): '', '800x600': '800x600', '640x480': '640x480', '320x240': '320x240'}, 'video_size', key=lambda x: -1 if \ not x[1] else int(x[0][:3])) st = app.config.get('video_see_self') self._ui.video_see_self_checkbutton.set_active(st) else: for opt_name in ('audio_input', 'audio_output', 'video_input', 'video_output', 'video_framerate', 'video_size'): combobox = self._ui.get_object(opt_name + '_combobox') combobox.set_sensitive(False) # STUN st = app.config.get('use_stun_server') self._ui.stun_checkbutton.set_active(st) self._ui.stun_server_entry.set_text(app.config.get('stun_server')) if not st: self._ui.stun_server_entry.set_sensitive(False) ### Advanced tab ### ## Applications (open links with) if os.name == 'nt': self._ui.custom_apps_frame.set_no_show_all(True) self._ui.custom_apps_frame.hide() else: self._ui.custom_apps_frame.hide() self._ui.custom_apps_frame.set_no_show_all(True) if app.config.get('autodetect_browser_mailer'): self._ui.applications_combobox.set_active(0) else: self._ui.applications_combobox.set_active(1) self._ui.custom_apps_frame.show() self._ui.custom_browser_entry.set_text( app.config.get('custombrowser')) self._ui.custom_mail_client_entry.set_text( app.config.get('custommailapp')) self._ui.custom_file_manager_entry.set_text( app.config.get('custom_file_manager')) ## Miscellaneous # Proxy self.update_proxy_list() # Log status changes of contacts st = app.config.get('log_contact_status_changes') self._ui.log_show_changes_checkbutton.set_active(st) # Enable debug logging if sys.platform == 'win32': self._ui.enable_logging.set_active(app.get_win_debug_mode()) self._ui.enable_logging.show() self._ui.connect_signals(self) self.connect('key-press-event', self._on_key_press) self._ui.msg_treeview.get_model().connect( 'row-changed', self.on_msg_treemodel_row_changed) self._ui.msg_treeview.get_model().connect( 'row-deleted', self.on_msg_treemodel_row_deleted) self._ui.default_msg_treeview.get_model().connect( 'row-changed', self.on_default_msg_treemodel_row_changed) self.sounds_preferences = None self.theme_preferences = None self.show_all()
def __init__(self, account, contact, jid, name, show_account, groupchat=False): Gtk.ListBoxRow.__init__(self) self.get_style_context().add_class('start-chat-row') self.account = account self.account_label = app.get_account_label(account) self.show_account = show_account self.jid = jid self.contact = contact self.name = name self.groupchat = groupchat self.new = jid == '' grid = Gtk.Grid() grid.set_column_spacing(12) grid.set_size_request(260, -1) if self.groupchat: muc_icon = get_icon_name( 'muc-inactive' if self.new else 'muc-active') image = Gtk.Image.new_from_icon_name(muc_icon, Gtk.IconSize.DND) else: scale = self.get_scale_factor() avatar = app.contacts.get_avatar(account, jid, AvatarSize.CHAT, scale) if avatar is None: image = Gtk.Image.new_from_icon_name('avatar-default', Gtk.IconSize.DND) else: image = Gtk.Image.new_from_surface(avatar) image.set_size_request(AvatarSize.CHAT, AvatarSize.CHAT) grid.add(image) middle_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0) middle_box.set_hexpand(True) if self.name is None: if self.groupchat: self.name = _('Join Group Chat') else: self.name = _('Add Contact') self.name_label = Gtk.Label(label=self.name) self.name_label.set_ellipsize(Pango.EllipsizeMode.END) self.name_label.set_xalign(0) self.name_label.set_width_chars(25) self.name_label.set_halign(Gtk.Align.START) self.name_label.get_style_context().add_class('bold16') status = contact.show if contact else 'offline' css_class = helpers.get_css_show_color(status) if css_class is not None: self.name_label.get_style_context().add_class(css_class) middle_box.add(self.name_label) self.jid_label = Gtk.Label(label=jid) self.jid_label.set_ellipsize(Pango.EllipsizeMode.END) self.jid_label.set_xalign(0) self.jid_label.set_width_chars(25) self.jid_label.set_halign(Gtk.Align.START) self.jid_label.get_style_context().add_class('dim-label') middle_box.add(self.jid_label) grid.add(middle_box) if show_account: account_label = Gtk.Label(label=self.account_label) account_label.set_halign(Gtk.Align.START) account_label.set_valign(Gtk.Align.START) right_box = Gtk.Box() right_box.set_vexpand(True) right_box.add(account_label) grid.add(right_box) self.add(grid) self.show_all()
def __init__(self, account, jids, preselected=None): """ This window is used to trasform a one-to-one chat to a MUC. We do 2 things: first select the server and then make a guests list """ self.instances.append(self) self.account = account self.auto_jids = jids self.preselected_jids = preselected self.xml = get_builder('chat_to_muc_window.ui') self.window = self.xml.get_object('chat_to_muc_window') for widget_to_add in ('invite_button', 'cancel_button', 'server_list_comboboxentry', 'guests_treeview', 'guests_store', 'server_and_guests_hseparator', 'server_select_label'): self.__dict__[widget_to_add] = self.xml.get_object(widget_to_add) server_list = [] self.servers = Gtk.ListStore(str) self.server_list_comboboxentry.set_model(self.servers) cell = Gtk.CellRendererText() self.server_list_comboboxentry.pack_start(cell, True) self.server_list_comboboxentry.add_attribute(cell, 'text', 0) # get the muc server of our server if 'jabber' in app.connections[account].muc_jid: server_list.append(app.connections[account].muc_jid['jabber']) # add servers or recently joined groupchats recently_groupchat = app.config.get_per('accounts', account, 'recent_groupchats').split() for g in recently_groupchat: server = app.get_server_from_jid(g) if server not in server_list and not server.startswith('irc'): server_list.append(server) # add a default server if not server_list: server_list.append('conference.jabber.org') for s in server_list: self.servers.append([s]) self.server_list_comboboxentry.set_active(0) # set treeview # name, jid self.guests_store.set_sort_column_id(1, Gtk.SortType.ASCENDING) self.guests_treeview.get_selection().set_mode( Gtk.SelectionMode.MULTIPLE) # All contacts beside the following can be invited: # transports, zeroconf contacts, minimized groupchats def invitable(contact, contact_transport=None): return (contact.jid not in self.auto_jids and contact.jid != app.get_jid_from_account(account) and contact.jid not in app.interface.minimized_controls[account] and not contact.is_transport() and contact_transport in ('jabber', None)) # set jabber id and pseudos for account_ in app.contacts.get_accounts(): if app.connections[account_].is_zeroconf: continue for jid in app.contacts.get_jid_list(account_): contact = app.contacts.get_contact_with_highest_priority( account_, jid) contact_transport = app.get_transport_name_from_jid(jid) # Add contact if it can be invited if invitable(contact, contact_transport) and \ contact.show not in ('offline', 'error'): icon_name = get_icon_name(contact.show) name = contact.name if name == '': name = jid.split('@')[0] iter_ = self.guests_store.append([icon_name, name, jid]) # preselect treeview rows if self.preselected_jids and jid in self.preselected_jids: path = self.guests_store.get_path(iter_) self.guests_treeview.get_selection().select_path(path) # show all self.window.show_all() self.xml.connect_signals(self)
def __init__(self): Gtk.ApplicationWindow.__init__(self) self.set_application(app.app) self.set_position(Gtk.WindowPosition.CENTER) self.set_show_menubar(False) self.set_title(_('Preferences')) self._ui = get_builder('preferences_window.ui') self.add(self._ui.preferences_window) ### General tab ### ## Behavior of Windows and Tabs # Set default for single window type choices = c_config.opt_one_window_types type_ = app.config.get('one_message_window') if type_ in choices: self._ui.one_window_type_combobox.set_active(choices.index(type_)) else: self._ui.one_window_type_combobox.set_active(0) # Show roster on startup choices = c_config.opt_show_roster_on_startup type_ = app.config.get('show_roster_on_startup') if type_ in choices: self._ui.show_roster_on_startup.set_active(choices.index(type_)) else: self._ui.show_roster_on_startup.set_active(0) # Quit on roster x st = app.config.get('quit_on_roster_x_button') self._ui.quit_on_roster_x_checkbutton.set_active(st) # Tab placement st = app.config.get('tabs_position') if st == 'top': self._ui.tabs_placement.set_active(0) elif st == 'bottom': self._ui.tabs_placement.set_active(1) elif st == 'left': self._ui.tabs_placement.set_active(2) else: # right self._ui.tabs_placement.set_active(3) # Show avatar in tabs st = app.config.get('show_avatar_in_tabs') self._ui.show_avatar_in_tabs_checkbutton.set_active(st) ## Contact List Appearance # Display avatars in roster st = app.config.get('show_avatars_in_roster') self._ui.show_avatars_in_roster_checkbutton.set_active(st) # Display status msg under contact name in roster st = app.config.get('show_status_msgs_in_roster') self._ui.show_status_msgs_in_roster_checkbutton.set_active(st) # Display PEP in roster st1 = app.config.get('show_mood_in_roster') st2 = app.config.get('show_activity_in_roster') st3 = app.config.get('show_tunes_in_roster') st4 = app.config.get('show_location_in_roster') if st1 == st2 == st3 == st4: self._ui.show_pep_in_roster_checkbutton.set_active(st1) else: self._ui.show_pep_in_roster_checkbutton.set_inconsistent(True) # Sort contacts by show st = app.config.get('sort_by_show_in_roster') self._ui.sort_by_show_in_roster_checkbutton.set_active(st) st = app.config.get('sort_by_show_in_muc') self._ui.sort_by_show_in_muc_checkbutton.set_active(st) ### Chat tab ### ## General Settings # Enable auto copy st = app.config.get('auto_copy') self._ui.auto_copy.set_active(st) ## Chat Settings # Use speller if app.is_installed('GSPELL'): st = app.config.get('use_speller') self._ui.speller_checkbutton.set_active(st) else: self._ui.speller_checkbutton.set_sensitive(False) # XEP-0184 positive ack st = app.config.get('positive_184_ack') self._ui.positive_184_ack_checkbutton.set_active(st) # Ignore XHTML st = app.config.get('show_xhtml') self._ui.xhtml_checkbutton.set_active(st) # Print status messages in single chats st = app.config.get('print_status_in_chats') self._ui.print_status_in_chats_checkbutton.set_active(st) # Show subject on join st = app.config.get('show_subject_on_join') self._ui.subject_on_join_checkbutton.set_active(st) # Group chat settings threshold_model = self._ui.sync_threshold_combobox.get_model() days = app.config.get_options('threshold_options', return_type=int) for day in days: if day == 0: label = _('No threshold') else: label = ngettext('%i day', '%i days', day, day, day) threshold_model.append([str(day), label]) public_threshold = app.config.get('public_room_sync_threshold') self._ui.sync_threshold_combobox.set_id_column(0) self._ui.sync_threshold_combobox.set_active_id(str(public_threshold)) st = app.config.get('print_join_left_default') self._ui.join_leave_checkbutton.set_active(st) st = app.config.get('print_status_muc_default') self._ui.status_change_checkbutton.set_active(st) # Displayed chat state notifications st = app.config.get('show_chatstate_in_tabs') self._ui.show_chatstate_in_tabs.set_active(st) st = app.config.get('show_chatstate_in_roster') self._ui.show_chatstate_in_roster.set_active(st) st = app.config.get('show_chatstate_in_banner') self._ui.show_chatstate_in_banner.set_active(st) ### Notifications tab ### ## Visual Notifications # Systray icon if app.config.get('trayicon') == 'never': self._ui.systray_combobox.set_active(0) elif app.config.get('trayicon') == 'on_event': self._ui.systray_combobox.set_active(1) else: # always self._ui.systray_combobox.set_active(2) # Notify on new event if app.config.get('autopopup'): self._ui.on_event_received_combobox.set_active(0) elif app.config.get('notify_on_new_message'): self._ui.on_event_received_combobox.set_active(1) else: # only show in roster self._ui.on_event_received_combobox.set_active(2) # Notify on online statuses st = app.config.get('notify_on_signin') self._ui.notify_on_signin_checkbutton.set_active(st) # Notify on offline statuses st = app.config.get('notify_on_signout') self._ui.notify_on_signout_checkbutton.set_active(st) # Auto popup when away st = app.config.get('autopopupaway') self._ui.auto_popup_away_checkbutton.set_active(st) # Auto popup when chat already open st = app.config.get('autopopup_chat_opened') self._ui.auto_popup_chat_opened_checkbutton.set_active(st) ## Sounds # Sounds if app.config.get('sounds_on'): self._ui.play_sounds_checkbutton.set_active(True) else: self._ui.manage_sounds_button.set_sensitive(False) # Allow sounds when dnd st = app.config.get('sounddnd') self._ui.sound_dnd_checkbutton.set_active(st) #### Status tab ### # Auto away st = app.config.get('autoaway') self._ui.auto_away_checkbutton.set_active(st) # Auto away time st = app.config.get('autoawaytime') self._ui.auto_away_time_spinbutton.set_value(st) self._ui.auto_away_time_spinbutton.set_sensitive( app.config.get('autoaway')) # Auto away message st = app.config.get('autoaway_message') self._ui.auto_away_message_entry.set_text(st) self._ui.auto_away_message_entry.set_sensitive( app.config.get('autoaway')) # Auto xa st = app.config.get('autoxa') self._ui.auto_xa_checkbutton.set_active(st) # Auto xa time st = app.config.get('autoxatime') self._ui.auto_xa_time_spinbutton.set_value(st) self._ui.auto_xa_time_spinbutton.set_sensitive( app.config.get('autoxa')) # Auto xa message st = app.config.get('autoxa_message') self._ui.auto_xa_message_entry.set_text(st) self._ui.auto_xa_message_entry.set_sensitive(app.config.get('autoxa')) if not idle.Monitor.is_available(): self._ui.autoaway_table.set_sensitive(False) # Restore last status st = self.get_per_account_option('restore_last_status') if st == 'mixed': self._ui.restore_last_status_checkbutton.set_inconsistent(True) else: self._ui.restore_last_status_checkbutton.set_active(st) # Ask for status when online/offline st = app.config.get('ask_online_status') self._ui.prompt_online_status_message_checkbutton.set_active(st) st = app.config.get('ask_offline_status') self._ui.prompt_offline_status_message_checkbutton.set_active(st) # Default status messages self.fill_default_msg_treeview() # Status messages renderer = Gtk.CellRendererText() renderer.connect('edited', self.on_msg_cell_edited) renderer.set_property('editable', True) col = Gtk.TreeViewColumn('name', renderer, text=0) self._ui.msg_treeview.append_column(col) self.fill_msg_treeview() buf = self._ui.msg_textview.get_buffer() buf.connect('end-user-action', self.on_msg_textview_changed) ### Style tab ### # Themes self.changed_id = self._ui.theme_combobox.connect( 'changed', self.on_theme_combobox_changed) self.update_theme_list() # Dark theme self._ui.dark_theme_combobox.set_active_id( str(app.config.get('dark_theme'))) # Emoticons emoticon_themes = helpers.get_available_emoticon_themes() for theme in emoticon_themes: self._ui.emoticons_combobox.append_text(theme) config_theme = app.config.get('emoticons_theme') if config_theme not in emoticon_themes: config_theme = 'font' self._ui.emoticons_combobox.set_id_column(0) self._ui.emoticons_combobox.set_active_id(config_theme) self._ui.ascii_emoticons.set_active(app.config.get('ascii_emoticons')) # Iconset model = Gtk.ListStore(str, str) renderer_image = Gtk.CellRendererPixbuf() renderer_text = Gtk.CellRendererText() renderer_text.set_property('xpad', 5) self._ui.iconset_combobox.pack_start(renderer_image, False) self._ui.iconset_combobox.pack_start(renderer_text, True) self._ui.iconset_combobox.add_attribute(renderer_text, 'text', 1) self._ui.iconset_combobox.add_attribute(renderer_image, 'icon_name', 0) self._ui.iconset_combobox.set_model(model) for index, iconset_name in enumerate(get_available_iconsets()): icon_name = get_icon_name('online', iconset=iconset_name) model.append([icon_name, iconset_name]) if app.config.get('iconset') == iconset_name: self._ui.iconset_combobox.set_active(index) # Use transports iconsets st = app.config.get('use_transports_iconsets') self._ui.transports_iconsets_checkbutton.set_active(st) ### Audio/Video tab ### def create_av_combobox( opt_name, device_dict, config_name=None, # This key is there to give the first index to autovideosrc and co. key=lambda x: '' if x[1].startswith('auto') else x[0].lower()): combobox = self._ui.get_object(opt_name + '_combobox') cell = Gtk.CellRendererText() cell.set_property('ellipsize', Pango.EllipsizeMode.END) cell.set_property('ellipsize-set', True) combobox.pack_start(cell, True) combobox.add_attribute(cell, 'text', 0) model = Gtk.ListStore(str, str) combobox.set_model(model) if config_name: config = app.config.get(config_name) else: config = app.config.get(opt_name + '_device') for index, (name, value) in enumerate( sorted(device_dict.items(), key=key)): model.append((name, value)) if config == value: combobox.set_active(index) if HAS_GST and app.is_installed('FARSTREAM'): create_av_combobox('audio_input', AudioInputManager().get_devices()) create_av_combobox('audio_output', AudioOutputManager().get_devices()) create_av_combobox('video_input', VideoInputManager().get_devices()) create_av_combobox('video_framerate', { _('Default'): '', '15fps': '15/1', '10fps': '10/1', '5fps': '5/1', '2.5fps': '5/2' }, 'video_framerate', key=lambda x: -1 if not x[1] else float(x[0][:-3])) create_av_combobox('video_size', { _('Default'): '', '800x600': '800x600', '640x480': '640x480', '320x240': '320x240' }, 'video_size', key=lambda x: -1 if not x[1] else int(x[0][:3])) st = app.config.get('video_see_self') self._ui.video_see_self_checkbutton.set_active(st) def on_av_map(tab): label = self._ui.selected_video_output sink, widget, name = self.setup_video_output() if sink is None: log.error( 'Failed to obtain a working Gstreamer GTK+ sink, ' 'video support will be disabled') self._ui.video_input_combobox.set_sensitive(False) label.set_markup( _('<span color="red" font-weight="bold">' 'Unavailable</span>, video support will be disabled') ) return text = '' if name == 'gtkglsink': text = _('<span color="green" font-weight="bold">' 'OpenGL</span> accelerated') elif name == 'gtksink': text = _('<span color="yellow" font-weight="bold">' 'Unaccelerated</span>') label.set_markup(text) if self.av_pipeline is None: self.av_pipeline = Gst.Pipeline.new('preferences-pipeline') else: self.av_pipeline.set_state(Gst.State.NULL) self.av_pipeline.add(sink) self.av_sink = sink if self.av_widget is not None: tab.remove(self.av_widget) tab.add(widget) self.av_widget = widget src_name = app.config.get('video_input_device') try: self.av_src = Gst.parse_bin_from_description( src_name, True) except GLib.Error: log.error( 'Failed to parse "%s" as Gstreamer element,' ' falling back to autovideosrc', src_name) self.av_src = None if self.av_src is not None: self.av_pipeline.add(self.av_src) self.av_src.link(self.av_sink) self.av_pipeline.set_state(Gst.State.PLAYING) else: # Parsing the pipeline stored in video_input_device failed, # let’s try the default one. self.av_src = Gst.ElementFactory.make('autovideosrc', None) if self.av_src is None: log.error( 'Failed to obtain a working Gstreamer source,' ' video will be disabled.') self._ui.video_input_combobox.set_sensitive(False) return # Great, this succeeded, let’s store it back into the # config and use it. We’ve made autovideosrc the first # element in the combobox so we can pick index 0 without # worry. combobox = self._ui.video_input_combobox combobox.set_active(0) def on_av_unmap(tab): if self.av_pipeline is not None: self.av_pipeline.set_state(Gst.State.NULL) if self.av_src is not None: self.av_pipeline.remove(self.av_src) self.av_src = None if self.av_sink is not None: self.av_pipeline.remove(self.av_sink) self.av_sink = None if self.av_widget is not None: tab.remove(self.av_widget) self.av_widget = None self.av_pipeline = None self.av_pipeline = None self.av_src = None self.av_sink = None self.av_widget = None tab = self._ui.audio_video_tab tab.connect('map', on_av_map) tab.connect('unmap', on_av_unmap) else: for opt_name in ('audio_input', 'audio_output', 'video_input', 'video_framerate', 'video_size'): combobox = self._ui.get_object(opt_name + '_combobox') combobox.set_sensitive(False) # STUN st = app.config.get('use_stun_server') self._ui.stun_checkbutton.set_active(st) self._ui.stun_server_entry.set_text(app.config.get('stun_server')) if not st: self._ui.stun_server_entry.set_sensitive(False) ### Advanced tab ### ## Miscellaneous # Proxy self.update_proxy_list() # Log status changes of contacts st = app.config.get('log_contact_status_changes') self._ui.log_show_changes_checkbutton.set_active(st) self._ui.enable_logging.set_active(app.get_debug_mode()) self._ui.enable_logging.show() self._ui.connect_signals(self) self.connect('key-press-event', self._on_key_press) self._ui.msg_treeview.get_model().connect( 'row-changed', self.on_msg_treemodel_row_changed) self._ui.msg_treeview.get_model().connect( 'row-deleted', self.on_msg_treemodel_row_deleted) self._ui.default_msg_treeview.get_model().connect( 'row-changed', self.on_default_msg_treemodel_row_changed) self.sounds_preferences = None self.theme_preferences = None self.show_all()