Пример #1
0
    def _delete_jid_logs(self, liststore, list_of_paths):
        paths_len = len(list_of_paths)
        if paths_len == 0:  # nothing is selected
            return

        def on_ok():
            # delete all rows from db that match jid_id
            list_of_rowrefs = []
            for path in list_of_paths:  # make them treerowrefs (it's needed)
                list_of_rowrefs.append(
                    Gtk.TreeRowReference.new(liststore, path))

            for rowref in list_of_rowrefs:
                path = rowref.get_path()
                if path is None:
                    continue
                jid_id = liststore[path][1]
                del liststore[path]  # remove from UI
                # remove from db
                self.cur.execute(
                    '''
                        DELETE FROM logs
                        WHERE jid_id = ?
                        ''', (jid_id, ))

                # now delete "jid, jid_id" row from jids table
                self.cur.execute(
                    '''
                                DELETE FROM jids
                                WHERE jid_id = ?
                                ''', (jid_id, ))

            self.con.commit()

            self.AT_LEAST_ONE_DELETION_DONE = True

        NewConfirmationDialog(
            _('Delete'),
            ngettext('Delete Conversation', 'Delete Conversations', paths_len),
            ngettext(
                'Do you want to permanently delete this '
                'conversation with <b>%s</b>?',
                'Do you want to permanently delete these conversations?',
                paths_len, liststore[list_of_paths[0]][0]), [
                    DialogButton.make('Cancel'),
                    DialogButton.make('Delete', callback=on_ok)
                ],
            transient_for=self._ui.history_manager_window).show()
Пример #2
0
    def handle_incoming_gc_msg_event(self, msg_obj):
        if not msg_obj.gc_control:
            # we got a message from a room we're not in? ignore it
            return
        self.jid = msg_obj.jid
        sound = msg_obj.gc_control.highlighting_for_message(
            msg_obj.msgtxt, msg_obj.timestamp)[1]

        if msg_obj.nickname != msg_obj.gc_control.nick:
            self.do_sound = True
            if sound == 'received':
                self.sound_event = 'muc_message_received'
            elif sound == 'highlight':
                self.sound_event = 'muc_message_highlight'
            else:
                self.do_sound = False
        else:
            self.do_sound = False

        self.control = app.interface.msg_win_mgr.search_control(
            msg_obj.jid, self.account)

        if self.control is not None:
            self.control_focused = self.control.has_focus()

        if app.config.get('notify_on_new_message'):
            notify_for_muc = (app.config.notify_for_muc(self.jid)
                              or sound == 'highlight')
            if not notify_for_muc:
                self.do_popup = False

            elif self.control_focused:
                self.do_popup = False

            elif app.config.get('autopopupaway'):
                # always show notification
                self.do_popup = True

            elif app.connections[self.conn.name].connected in (2, 3):
                # we're online or chat
                self.do_popup = True

        self.popup_msg_type = 'gc_msg'
        self.popup_event_type = _('New Group Chat Message')

        if app.config.get('notification_preview_message'):
            self.popup_text = msg_obj.msgtxt

        type_events = ['printed_marked_gc_msg', 'printed_gc_msg']
        count = len(app.events.get_events(self.account, self.jid, type_events))

        contact = app.contacts.get_contact(self.account, self.jid)

        self.popup_title = i18n.ngettext(
            'New message from %(nickname)s',
            '%(n_msgs)i unread messages in %(groupchat_name)s', count) % {
                'nickname': msg_obj.nick,
                'n_msgs': count,
                'groupchat_name': contact.get_shown_name()
            }
Пример #3
0
 def build_sync_menu():
     menu = Gio.Menu()
     days = app.config.get('threshold_options').split(',')
     days = [int(day) for day in days]
     action_name = 'win.choose-sync-%s::' % control_id
     for day in days:
         if day == 0:
             label = _('No threshold')
         else:
             label = ngettext('%i day', '%i days', day, day, day)
         menu.append(label, '%s%s' % (action_name, day))
     return menu
Пример #4
0
    def _delete_logs(self, liststore, list_of_paths):
        paths_len = len(list_of_paths)
        if paths_len == 0:  # nothing is selected
            return

        def on_ok():
            # delete rows from db that match log_line_id
            list_of_rowrefs = []
            for path in list_of_paths:  # make them treerowrefs (it's needed)
                list_of_rowrefs.append(
                    Gtk.TreeRowReference.new(liststore, path))

            for rowref in list_of_rowrefs:
                path = rowref.get_path()
                if path is None:
                    continue
                log_line_id = liststore[path][0]
                del liststore[path]  # remove from UI
                # remove from db
                self.cur.execute(
                    '''
                        DELETE FROM logs
                        WHERE log_line_id = ?
                        ''', (log_line_id, ))

            self.con.commit()

            self.AT_LEAST_ONE_DELETION_DONE = True

        NewConfirmationDialog(
            _('Delete'),
            ngettext('Delete Message', 'Delete Messages', paths_len),
            ngettext('Do you want to permanently delete this message',
                     'Do you want to permanently delete these messages',
                     paths_len), [
                         DialogButton.make('Cancel'),
                         DialogButton.make('Delete', callback=on_ok)
                     ],
            transient_for=self._ui.history_manager_window).show()
Пример #5
0
 def updateCounter(self):
     """
     Display number of events on the top of window, sometimes it needs to be
     changed
     """
     count = len(self.__class__.entries)
     if count:
         self.new_entry_label.set_text(i18n.ngettext(
             'You have received new entries (and %d not displayed):',
             'You have received new entries (and %d not displayed):', count,
             count, count))
         self.next_button.set_sensitive(True)
     else:
         self.new_entry_label.set_text(_('You have received new entry:'))
         self.next_button.set_sensitive(False)
Пример #6
0
    def _delete_logs(self, liststore, list_of_paths):
        paths_len = len(list_of_paths)
        if paths_len == 0:  # nothing is selected
            return

        def on_ok(liststore, list_of_paths):
            # delete rows from db that match log_line_id
            list_of_rowrefs = []
            for path in list_of_paths:  # make them treerowrefs (it's needed)
                list_of_rowrefs.append(
                    Gtk.TreeRowReference.new(liststore, path))

            for rowref in list_of_rowrefs:
                path = rowref.get_path()
                if path is None:
                    continue
                log_line_id = liststore[path][0]
                del liststore[path]  # remove from UI
                # remove from db
                self.cur.execute(
                    '''
                        DELETE FROM logs
                        WHERE log_line_id = ?
                        ''', (log_line_id, ))

            self.con.commit()

            self.AT_LEAST_ONE_DELETION_DONE = True

        pri_text = i18n.ngettext(
            'Do you really want to delete the selected message?',
            'Do you really want to delete the selected messages?', paths_len)
        dialog = dialogs.ConfirmationDialog(
            pri_text,
            _('This is an irreversible operation.'),
            on_response_ok=(on_ok, liststore, list_of_paths))
        dialog.set_title(_('Deletion Confirmation'))
        ok_button = dialog.get_children()[0].get_children()[1].get_children(
        )[0]
        ok_button.grab_focus()
        dialog.set_transient_for(self.window)
Пример #7
0
    def handle_incoming_msg_event(self, msg_obj):
        # don't alert for carbon copied messages from ourselves
        if msg_obj.sent:
            return
        if not msg_obj.msgtxt:
            return
        self.jid = msg_obj.jid
        if msg_obj.mtype == 'pm':
            self.jid = msg_obj.fjid

        self.control = app.interface.msg_win_mgr.search_control(
            msg_obj.jid, self.account, msg_obj.resource)

        if self.control is None:
            if len(app.events.get_events(
                    self.account, msg_obj.jid, [msg_obj.mtype])) <= 1:
                self.first_unread = True
        else:
            self.control_focused = self.control.has_focus()

        if msg_obj.mtype == 'pm':
            nick = msg_obj.resource
        else:
            nick = app.get_name_from_jid(self.conn.name, self.jid)

        if self.first_unread:
            self.sound_event = 'first_message_received'
        elif self.control_focused:
            self.sound_event = 'next_message_received_focused'
        else:
            self.sound_event = 'next_message_received_unfocused'

        if app.config.get('notification_preview_message'):
            self.popup_text = msg_obj.msgtxt
            if self.popup_text and (self.popup_text.startswith('/me ') or \
            self.popup_text.startswith('/me\n')):
                self.popup_text = '* ' + nick + self.popup_text[3:]
        else:
            # We don't want message preview, do_preview = False
            self.popup_text = ''

        if msg_obj.mtype == 'normal': # single message
            self.popup_msg_type = 'normal'
            self.popup_event_type = _('New Single Message')
        elif msg_obj.mtype == 'pm':
            self.popup_msg_type = 'pm'
            self.popup_event_type = _('New Private Message')
        else: # chat message
            self.popup_msg_type = 'chat'
            self.popup_event_type = _('New Message')

        num_unread = len(app.events.get_events(self.conn.name, self.jid,
            ['printed_' + self.popup_msg_type, self.popup_msg_type]))
        self.popup_title = i18n.ngettext(
            'New message from %(nickname)s',
            '%(n_msgs)i unread messages from %(nickname)s',
            num_unread) % {'nickname': nick, 'n_msgs': num_unread}

        if app.config.get('notify_on_new_message'):
            if self.first_unread or (app.config.get('autopopup_chat_opened') \
            and not self.control_focused):
                if app.config.get('autopopupaway'):
                    # always show notification
                    self.do_popup = True
                if app.connections[self.conn.name].connected in (2, 3):
                    # we're online or chat
                    self.do_popup = True

        if msg_obj.attention and not app.config.get(
        'ignore_incoming_attention'):
            self.popup_timeout = 0
            self.do_popup = True
        else:
            self.popup_timeout = app.config.get('notification_timeout')

        if msg_obj.attention and not app.config.get(
        'ignore_incoming_attention') and app.config.get_per('soundevents',
        'attention_received', 'enabled'):
            self.sound_event = 'attention_received'
            self.do_sound = True
        elif self.first_unread and helpers.allow_sound_notification(
        self.conn.name, 'first_message_received'):
            self.do_sound = True
        elif not self.first_unread and self.control_focused and \
        helpers.allow_sound_notification(self.conn.name,
        'next_message_received_focused'):
            self.do_sound = True
        elif not self.first_unread and not self.control_focused and \
        helpers.allow_sound_notification(self.conn.name,
        'next_message_received_unfocused'):
            self.do_sound = True
Пример #8
0
def get_notification_icon_tooltip_dict():
    """
    Return a dict of the form {acct: {'show': show, 'message': message,
    'event_lines': [list of text lines to show in tooltip]}
    """
    # How many events before we show summarized, not per-user
    max_ungrouped_events = 10

    accounts = get_accounts_info()

    # Gather events. (With accounts, when there are more.)
    for account in accounts:
        account_name = account['name']
        account['event_lines'] = []
        # Gather events per-account
        pending_events = app.events.get_events(account=account_name)
        messages, non_messages = {}, {}
        total_messages, total_non_messages = 0, 0
        for jid in pending_events:
            for event in pending_events[jid]:
                if event.type_.count('file') > 0:
                    # This is a non-messagee event.
                    messages[jid] = non_messages.get(jid, 0) + 1
                    total_non_messages = total_non_messages + 1
                else:
                    # This is a message.
                    messages[jid] = messages.get(jid, 0) + 1
                    total_messages = total_messages + 1
        # Display unread messages numbers, if any
        if total_messages > 0:
            if total_messages > max_ungrouped_events:
                text = ngettext('%d message pending',
                                '%d messages pending',
                                total_messages,
                                total_messages,
                                total_messages)
                account['event_lines'].append(text)
            else:
                for jid in messages:
                    text = ngettext('%d message pending',
                                    '%d messages pending',
                                    messages[jid],
                                    messages[jid],
                                    messages[jid])
                    contact = app.contacts.get_first_contact_from_jid(
                        account['name'], jid)
                    text += ' '
                    if jid in app.gc_connected[account['name']]:
                        text += _('from group chat %s') % (jid)
                    elif contact:
                        name = contact.get_shown_name()
                        text += _('from user %s') % (name)
                    else:
                        text += _('from %s') % (jid)
                    account['event_lines'].append(text)

        # Display unseen events numbers, if any
        if total_non_messages > 0:
            if total_non_messages > max_ungrouped_events:
                text = ngettext('%d event pending',
                                '%d events pending',
                                total_non_messages,
                                total_non_messages,
                                total_non_messages)
                account['event_lines'].append(text)
            else:
                for jid in non_messages:
                    text = ngettext('%d event pending',
                                    '%d events pending',
                                    non_messages[jid],
                                    non_messages[jid],
                                    non_messages[jid])
                    text += ' ' + _('from user %s') % (jid)
                    account[account]['event_lines'].append(text)

    return accounts
Пример #9
0
    def handle_incoming_gc_msg_event(self, msg_obj):
        if not msg_obj.gc_control:
            # we got a message from a room we're not in? ignore it
            return
        self.jid = msg_obj.jid
        sound = msg_obj.gc_control.highlighting_for_message(
            msg_obj.msgtxt, msg_obj.properties.timestamp)[1]

        nick = msg_obj.properties.muc_nickname

        if nick == msg_obj.gc_control.nick:
            # A message from ourself
            return

        self.do_sound = True
        if sound == 'received':
            self.sound_event = 'muc_message_received'
        elif sound == 'highlight':
            self.sound_event = 'muc_message_highlight'
        else:
            self.do_sound = False

        self.control = app.interface.msg_win_mgr.search_control(
            msg_obj.jid, self.account)

        if self.control is not None:
            self.control_focused = self.control.has_focus()

        if app.settings.get('show_notifications'):
            contact = app.contacts.get_groupchat_contact(self.account,
                                                         self.jid)
            notify_for_muc = sound == 'highlight' or contact.can_notify()

            if not notify_for_muc:
                self.do_popup = False

            elif self.control_focused:
                self.do_popup = False

            elif app.settings.get('autopopupaway'):
                # always show notification
                self.do_popup = True

            elif app.connections[self.conn.name].status in ('online', 'chat'):
                # we're online or chat
                self.do_popup = True

        self.popup_msg_type = 'gc_msg'
        self.popup_event_type = _('New Group Chat Message')

        if app.settings.get('notification_preview_message'):
            self.popup_text = msg_obj.msgtxt
            if self.popup_text and (self.popup_text.startswith('/me ') or
                                    self.popup_text.startswith('/me\n')):
                self.popup_text = '* ' + nick + self.popup_text[3:]

        type_events = ['printed_marked_gc_msg', 'printed_gc_msg']
        count = len(app.events.get_events(self.account, self.jid, type_events))

        contact = app.contacts.get_contact(self.account, self.jid)

        self.popup_title = i18n.ngettext(
            'New message from %(nickname)s',
            '%(n_msgs)i unread messages in %(groupchat_name)s',
            count) % {'nickname': nick,
                      'n_msgs': count,
                      'groupchat_name': contact.get_shown_name()}
Пример #10
0
    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()
Пример #11
0
 def _on_accept_button_clicked(self, _widget):
     model = self._ui.items_list_treeview.get_model()
     iter_ = model.get_iter_first()
     if self.action == 'add':
         count = 0
         while iter_:
             if model[iter_][0]:
                 count += 1
                 # It is selected
                 message = _('%s suggested me to add you to my '
                             'contact list.' % self.jid_from)
                 # Keep same groups and same nickname
                 groups = model[iter_][3].split(', ')
                 if groups == ['']:
                     groups = []
                 jid = model[iter_][1]
                 if app.jid_is_transport(self.jid_from):
                     con = app.connections[self.account]
                     con.get_module('Presence').automatically_added.append(
                         jid)
                 app.interface.roster.req_sub(self,
                                              jid,
                                              message,
                                              self.account,
                                              groups=groups,
                                              nickname=model[iter_][2],
                                              auto_auth=True)
             iter_ = model.iter_next(iter_)
         InformationDialog(
             i18n.ngettext('Added %d contact', 'Added %d contacts', count,
                           count, count))
     elif self.action == 'modify':
         count = 0
         while iter_:
             if model[iter_][0]:
                 count += 1
                 # It is selected
                 jid = model[iter_][1]
                 # Keep same groups and same nickname
                 groups = model[iter_][3].split(', ')
                 if groups == ['']:
                     groups = []
                 for contact in app.contacts.get_contact(self.account, jid):
                     contact.name = model[iter_][2]
                 con = app.connections[self.account]
                 con.get_module('Roster').update_contact(
                     jid, model[iter_][2], groups)
                 con.get_module('Roster').draw_contact(jid, self.account)
                 # Update opened chats
                 ctrl = app.interface.msg_win_mgr.get_control(
                     jid, self.account)
                 if ctrl:
                     ctrl.update_ui()
                     win = app.interface.msg_win_mgr.get_window(
                         jid, self.account)
                     win.redraw_tab(ctrl)
                     win.show_title()
             iter_ = model.iter_next(iter_)
     elif self.action == 'delete':
         count = 0
         while iter_:
             if model[iter_][0]:
                 count += 1
                 # It is selected
                 jid = model[iter_][1]
                 app.connections[self.account].get_module(
                     'Presence').unsubscribe(jid)
                 app.interface.roster.remove_contact(jid, self.account)
                 app.contacts.remove_jid(self.account, jid)
             iter_ = model.iter_next(iter_)
         InformationDialog(
             i18n.ngettext('Removed %d contact', 'Removed %d contacts',
                           count, count, count))
     self.destroy()
Пример #12
0
    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()