Ejemplo n.º 1
0
 def set_form(self, form):
     if self._current_form is not None:
         self.remove(self._current_form)
         self._current_form.destroy()
     self._current_form = DataFormWidget(form)
     self._current_form.connect('is-valid', self._on_is_valid)
     self._current_form.validate()
     self.pack_start(self._current_form, True, True, 0)
     self._current_form.show_all()
Ejemplo n.º 2
0
    def __init__(self, account, jid, own_affiliation, form=None):
        Gtk.ApplicationWindow.__init__(self)
        self.set_application(app.app)
        self.set_position(Gtk.WindowPosition.CENTER)
        self.set_show_menubar(False)
        self.set_title(_('Group Chat Configuration'))
        self._destroyed = False

        self.account = account
        self.jid = jid
        self._own_affiliation = own_affiliation

        self._ui = get_builder('groupchat_config.ui')
        self.add(self._ui.grid)

        # Activate Add button only for Admins and Owners
        if self._own_affiliation in ('admin', 'owner'):
            self._ui.add_button.set_sensitive(True)
            self._ui.add_button.set_tooltip_text('')

        disco_info = app.logger.get_last_disco_info(self.jid)
        visible = disco_info.supports(nbxmpp.NS_REGISTER)
        self._ui.reserved_name_column.set_visible(visible)
        self._ui.info_button.set_sensitive(False)

        self._form = form
        self._affiliations = {}
        self._new_affiliations = {}

        con = app.connections[self.account]
        for affiliation in ('owner', 'admin', 'member', 'outcast'):
            con.get_module('MUC').get_affiliation(
                self.jid,
                affiliation,
                callback=self._on_affiliations_received,
                user_data=affiliation)

        if form is not None:
            self._ui.stack.set_visible_child_name('config')
            self._data_form_widget = DataFormWidget(form)
            self._data_form_widget.connect('is-valid', self._on_is_valid)
            self._data_form_widget.validate()
            self._ui.config_grid.add(self._data_form_widget)
        else:
            self._ui.stack.get_child_by_name('config').hide()
            self._ui.stack.get_child_by_name('config').set_no_show_all(True)
            self._ui.stack.set_visible_child_name('affiliation')

        self._ui.connect_signals(self)
        self.connect('delete-event', self._cancel)
        self.connect('destroy', self._on_destroy)
        self.connect('key-press-event', self._on_key_press)
        self.show_all()
        self._ui.stack.notify('visible-child-name')
Ejemplo n.º 3
0
 def _show_form(self, form):
     if self._dataform_widget is not None:
         self.remove(self._dataform_widget)
         self._dataform_widget.destroy()
     if form is None:
         return
     form = dataforms.extend_form(node=form)
     self._dataform_widget = DataFormWidget(form)
     self._dataform_widget.connect('is-valid', self._on_is_valid)
     self._dataform_widget.validate()
     self._dataform_widget.show_all()
     self.add(self._dataform_widget)
Ejemplo n.º 4
0
    def _show_form(self, form):
        if self._dataform_widget is not None:
            self.remove(self._dataform_widget)
            self._dataform_widget.destroy()
        if form is None:
            return

        form = dataforms.extend_form(node=form)

        self._dataform_widget = DataFormWidget(form,
                                               options={'read-only': True})
        self._dataform_widget.show_all()
        self.add(self._dataform_widget)
Ejemplo n.º 5
0
    def _on_get_success(self, form, is_form):
        log.info('Show Form page')
        self._is_form = is_form
        if is_form:
            dataform = dataforms.ExtendForm(node=form)
            self._data_form_widget = DataFormWidget(dataform)
        else:
            from gajim import config
            self._data_form_widget = config.FakeDataForm(form)

        page = self.get_nth_page(Page.FORM)
        page.pack_start(self._data_form_widget, True, True, 0)
        self._data_form_widget.show_all()
        self.set_current_page(Page.FORM)
Ejemplo n.º 6
0
class NextStage(Page):
    def __init__(self):
        Page.__init__(self)
        self.set_valign(Gtk.Align.FILL)
        self.complete = False
        self.title = _('Change Password')
        self._current_form = None

        self.show_all()

    def _on_is_valid(self, _widget, is_valid):
        self.complete = is_valid
        self.get_toplevel().update_page_complete()

    def set_form(self, form):
        if self._current_form is not None:
            self.remove(self._current_form)
            self._current_form.destroy()
        self._current_form = DataFormWidget(form)
        self._current_form.connect('is-valid', self._on_is_valid)
        self._current_form.validate()
        self.pack_start(self._current_form, True, True, 0)
        self._current_form.show_all()

    def get_submit_form(self):
        return self._current_form.get_submit_form()
Ejemplo n.º 7
0
 def __init__(self):
     Gtk.Window.__init__(self, title="Data Form Test")
     self.set_default_size(600, 600)
     options = {
         'left-width': 100,
         'form-width': 435,
     }
     self._widget = DataFormWidget(extend_form(node=nbxmpp.Node(node=FORM)),
                                   options)
     self.add(self._widget)
     self.show()
Ejemplo n.º 8
0
    def __init__(self, data):
        transient = app.app.get_active_window()
        Gtk.ApplicationWindow.__init__(self, title="Data Form Test")
        self.set_transient_for(transient)
        self.set_default_size(600, 400)

        self._account = data['account']
        self._jid = data['jid']

        self._form_widget = DataFormWidget(
            extend_form(node=nbxmpp.Node(node=data['form'])))
        box = Gtk.Box(orientation='vertical', spacing=12)
        box.add(self._form_widget)

        button = Gtk.Button(label=data['submit-text'])
        button.connect('clicked', self._on_send_clicked)
        button.set_halign(Gtk.Align.END)
        box.add(button)

        self.add(box)
        self.show_all()
Ejemplo n.º 9
0
    def _build_dataform(self, form, is_form):
        if not is_form:
            return FakeDataFormWidget(form)

        dataform = dataforms.extend_form(node=form)

        form_widget = DataFormWidget(dataform)
        form_widget.connect('is-valid', self._on_is_valid)
        form_widget.validate()
        return form_widget
Ejemplo n.º 10
0
class Form(Gtk.Box):

    type_ = Gtk.AssistantPageType.CUSTOM
    title = _('Search')
    complete = True

    def __init__(self):
        super().__init__(orientation=Gtk.Orientation.VERTICAL)
        self.set_spacing(18)
        self._dataform_widget = None
        self.show_all()

    @property
    def search_form(self):
        return self._dataform_widget.get_submit_form()

    def clear(self):
        self._show_form(None)

    def process_search_form(self, form):
        self._show_form(form)

    def _show_form(self, form):
        if self._dataform_widget is not None:
            self.remove(self._dataform_widget)
            self._dataform_widget.destroy()
        if form is None:
            return

        options = {'form-width': 350}

        form = dataforms.extend_form(node=form)
        self._dataform_widget = DataFormWidget(form, options=options)
        self._dataform_widget.connect('is-valid', self._on_is_valid)
        self._dataform_widget.validate()
        self._dataform_widget.show_all()
        self.add(self._dataform_widget)

    def _on_is_valid(self, _widget, is_valid):
        self.get_toplevel().set_stage_complete(is_valid)

    def get_submit_form(self):
        return self._dataform_widget.get_submit_form()
Ejemplo n.º 11
0
class FormDialog(Gtk.ApplicationWindow):
    def __init__(self, data):
        transient = app.app.get_active_window()
        Gtk.ApplicationWindow.__init__(self, title="Data Form Test")
        self.set_transient_for(transient)
        self.set_default_size(600, 400)

        self._account = data['account']
        self._jid = data['jid']

        self._form_widget = DataFormWidget(
            extend_form(node=nbxmpp.Node(node=data['form'])))
        box = Gtk.Box(orientation='vertical', spacing=12)
        box.add(self._form_widget)

        button = Gtk.Button(label=data['submit-text'])
        button.connect('clicked', self._on_send_clicked)
        button.set_halign(Gtk.Align.END)
        box.add(button)

        self.add(box)
        self.show_all()

    def _on_send_clicked(self, _button):
        form = self._form_widget.get_submit_form()
        app.nec.push_outgoing_event(
            MessageOutgoingEvent(None,
                                 account=self._account,
                                 jid=self._jid,
                                 form_node=form,
                                 is_loggable=False))
        control = find_control(self._account, self._jid)
        if control is None:
            return
        control.add_status_message('Form has successfully been sent')
        self.destroy()
Ejemplo n.º 12
0
    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()
Ejemplo n.º 13
0
class SingleMessageWindow(Gtk.ApplicationWindow):
    """
    SingleMessageWindow can send or show a received singled message depending on
    action argument which can be 'send' or 'receive'
    """
    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 on_single_message_window_destroy(self, widget):
        c = app.contacts.get_contact_with_highest_priority(
            self.account, self.from_whom)
        if not c:
            # Groupchat is maybe already destroyed
            return
        if c.is_groupchat and self.from_whom not in \
        app.interface.minimized_controls[self.account] and self.action == \
        'receive' and app.events.get_nb_roster_events(self.account,
        self.from_whom, types=['chat', 'normal']) == 0:
            app.interface.roster.remove_groupchat(self.from_whom, self.account)

    def set_cursor_to_end(self):
        end_iter = self.message_tv_buffer.get_end_iter()
        self.message_tv_buffer.place_cursor(end_iter)

    def save_pos(self):
        # save the window size and position
        x, y = self._ui.single_message_window.get_position()
        app.config.set('single-msg-x-position', x)
        app.config.set('single-msg-y-position', y)
        width, height = self._ui.single_message_window.get_size()
        app.config.set('single-msg-width', width)
        app.config.set('single-msg-height', height)

    def on_single_message_window_delete_event(self, window, ev):
        self.save_pos()

    def on_show_contact_info_button_clicked(self, widget):
        """
        Ask for vCard
        """
        entry = self._ui.to_entry.get_text().strip()

        keys = sorted(self.completion_dict.keys())
        for key in keys:
            contact = self.completion_dict[key]
            if entry in key:
                entry = contact.jid
                break

        if entry in app.interface.instances[self.account]['infos']:
            app.interface.instances[
                self.account]['infos'][entry].window.present()
        else:
            contact = app.contacts.create_contact(jid=entry,
                                                  account=self.account)
            app.interface.instances[self.account]['infos'][entry] = \
                     vcard.VcardWindow(contact, self.account)
            # Remove xmpp page
            app.interface.instances[self.account]['infos'][entry].xml.\
                     get_object('information_notebook').remove_page(0)

    def on_to_entry_changed(self, widget):
        entry = self._ui.to_entry.get_text()
        is_empty = bool(not entry == '' and not ',' in entry)
        self._ui.show_contact_info_button.set_sensitive(is_empty)

    def prepare_widgets_for(self, action):
        if len(app.connections) > 1:
            if action == 'send':
                title = _('Single Message using account %s') % self.account
            else:
                title = _('Single Message in account %s') % self.account
        else:
            title = _('Single Message')

        if action == 'send':  # prepare UI for Sending
            title = _('Send %s') % title
            self._ui.send_button.show()
            self._ui.send_and_close_button.show()
            self._ui.reply_button.hide()
            self._ui.close_button.hide()

            self._ui.send_grid.show()
            self._ui.received_grid.hide()

            if self.message:  # we come from a reply?
                self._ui.show_contact_info_button.set_sensitive(True)
                self._ui.message_textview.grab_focus()
                self.message_tv_buffer.set_text(self.message)
                GLib.idle_add(self.set_cursor_to_end)
            else:  # we write a new message (not from reply)
                if self.to:  # do we already have jid?
                    self._ui.subject_entry.grab_focus()

        elif action == 'receive':  # prepare UI for Receiving
            title = _('Received %s') % title
            self._ui.reply_button.show()
            self._ui.close_button.show()
            self._ui.send_button.hide()
            self._ui.send_and_close_button.hide()
            self._ui.reply_button.grab_focus()

            self._ui.received_grid.show()
            self._ui.send_grid.hide()

            if self.message:
                self.conversation_textview.print_real_text(self.message)
            fjid = self.from_whom
            if self.resource:
                fjid += '/' + self.resource  # Full jid of sender (with resource)
            self._ui.from_entry_label.set_text(fjid)

        elif action == 'form':  # prepare UI for Receiving
            title = self.form_widget.title
            title = _('Form: %s') % title
            self._ui.send_button.hide()
            self._ui.send_and_close_button.hide()
            self._ui.reply_button.show()
            self._ui.close_button.show()

            self._ui.send_grid.hide()
            self._ui.received_grid.show()

            fjid = self.from_whom
            if self.resource:
                fjid += '/' + self.resource  # Full jid of sender (with resource)
            self._ui.from_entry_label.set_text(fjid)

        self._ui.single_message_window.set_title(title)

    def on_close_button_clicked(self, widget):
        self.save_pos()
        self._ui.single_message_window.destroy()

    def update_char_counter(self, widget):
        characters_no = self.message_tv_buffer.get_char_count()
        self._ui.count_chars_label.set_text(
            _('Characters typed: %s') % str(characters_no))

    def send_single_message(self):
        if not app.account_is_connected(self.account):
            # if offline or connecting
            ErrorDialog(
                _('Connection not available'),
                _('Please make sure you are connected with "%s".') %
                self.account)
            return True
        if isinstance(self.to, list):
            sender_list = []
            for i in self.to:
                if i[0].resource:
                    sender_list.append(i[0].jid + '/' + i[0].resource)
                else:
                    sender_list.append(i[0].jid)
        else:
            sender_list = [
                j.strip() for j in self._ui.to_entry.get_text().split(',')
            ]

        subject = self._ui.subject_entry.get_text()
        begin, end = self.message_tv_buffer.get_bounds()
        message = self.message_tv_buffer.get_text(begin, end, True)

        if self.form_widget:
            form_node = self.form_widget.get_submit_form()
        else:
            form_node = None

        recipient_list = []

        for to_whom_jid in sender_list:
            if to_whom_jid in self.completion_dict:
                to_whom_jid = self.completion_dict[to_whom_jid].jid
            try:
                to_whom_jid = helpers.parse_jid(to_whom_jid)
            except helpers.InvalidFormat:
                ErrorDialog(
                    _('Invalid XMPP Address'),
                    _('It is not possible to send a message to %s, this '
                      'XMPP Address is not valid.') % to_whom_jid)
                return True

            if '/announce/' in to_whom_jid:
                con = app.connections[self.account]
                con.get_module('Announce').set_announce(
                    to_whom_jid, subject, message)
                continue

            recipient_list.append(to_whom_jid)

        app.nec.push_outgoing_event(
            MessageOutgoingEvent(None,
                                 account=self.account,
                                 jid=recipient_list,
                                 message=message,
                                 type_='normal',
                                 subject=subject,
                                 form_node=form_node))

        self._ui.subject_entry.set_text('')  # we sent ok, clear the subject
        self.message_tv_buffer.set_text('')  # we sent ok, clear the textview

    def on_send_button_clicked(self, widget):
        self.send_single_message()

    def on_reply_button_clicked(self, widget):
        # we create a new blank window to send and we preset RE: and to jid
        self.subject = _('RE: %s') % self.subject
        self.message = _('%s wrote:\n') % self.from_whom + self.message
        # add > at the begining of each line
        self.message = self.message.replace('\n', '\n> ') + '\n\n'
        self._ui.single_message_window.destroy()
        SingleMessageWindow(self.account,
                            to=self.from_whom,
                            action='send',
                            from_whom=self.from_whom,
                            subject=self.subject,
                            message=self.message,
                            session=self.session)

    def on_send_and_close_button_clicked(self, widget):
        if self.send_single_message():
            return
        self.save_pos()
        self._ui.single_message_window.destroy()

    def on_single_message_window_key_press_event(self, widget, event):
        if event.keyval == Gdk.KEY_Escape:  # ESCAPE
            self.save_pos()
            self._ui.single_message_window.destroy()
Ejemplo n.º 14
0
class GroupchatConfig(Gtk.ApplicationWindow):
    def __init__(self, account, jid, own_affiliation, form=None):
        Gtk.ApplicationWindow.__init__(self)
        self.set_application(app.app)
        self.set_position(Gtk.WindowPosition.CENTER)
        self.set_show_menubar(False)
        self.set_title(_('Group Chat Configuration'))
        self._destroyed = False

        self.account = account
        self.jid = jid
        self._own_affiliation = own_affiliation

        self._ui = get_builder('groupchat_config.ui')
        self.add(self._ui.grid)

        # Activate Add button only for Admins and Owners
        if self._own_affiliation in ('admin', 'owner'):
            self._ui.add_button.set_sensitive(True)
            self._ui.add_button.set_tooltip_text('')

        visible = muc_caps_cache.supports(jid, nbxmpp.NS_REGISTER)
        self._ui.reserved_name_column.set_visible(visible)
        self._ui.info_button.set_sensitive(False)

        self._form = form
        self._affiliations = {}
        self._new_affiliations = {}

        con = app.connections[self.account]
        for affiliation in ('owner', 'admin', 'member', 'outcast'):
            con.get_module('MUC').get_affiliation(
                self.jid,
                affiliation,
                callback=self._on_affiliations_received,
                user_data=affiliation)

        if form is not None:
            self._ui.stack.set_visible_child_name('config')
            self._data_form_widget = DataFormWidget(form)
            self._data_form_widget.connect('is-valid', self._on_is_valid)
            self._data_form_widget.validate()
            self._ui.config_grid.add(self._data_form_widget)
        else:
            self._ui.stack.get_child_by_name('config').hide()
            self._ui.stack.get_child_by_name('config').set_no_show_all(True)
            self._ui.stack.set_visible_child_name('affiliation')

        self._ui.connect_signals(self)
        self.connect('delete-event', self._cancel)
        self.connect('destroy', self._on_destroy)
        self.connect('key-press-event', self._on_key_press)
        self.show_all()
        self._ui.stack.notify('visible-child-name')

    def _on_is_valid(self, _widget, is_valid):
        self._ui.ok_button.set_sensitive(is_valid)

    def _get_current_treeview(self):
        page_name = self._ui.stack.get_visible_child_name()
        return getattr(self._ui, '%s_treeview' % page_name)

    def _on_add(self, *args):
        page_name = self._ui.stack.get_visible_child_name()
        if page_name == 'outcast':
            affiliation_edit, jid_edit = self._allowed_to_edit('outcast')
            text = None
            affiliation = 'outcast'
        else:
            affiliation_edit, jid_edit = self._allowed_to_edit('member')
            text = _('Member')
            affiliation = 'member'

        treeview = self._get_current_treeview()
        iter_ = treeview.get_model().append([None,
                                             None,
                                             None,
                                             affiliation,
                                             text,
                                             affiliation_edit,
                                             jid_edit])

        # Scroll to added row
        path = treeview.get_model().get_path(iter_)
        treeview.scroll_to_cell(path, None, False, 0, 0)
        treeview.get_selection().unselect_all()
        treeview.get_selection().select_path(path)

    def _on_remove(self, *args):
        treeview = self._get_current_treeview()
        model, paths = treeview.get_selection().get_selected_rows()

        owner_count = self._get_owner_count()
        references = []
        for path in paths:
            if model[path][MUCUser.AFFILIATION] == 'owner':
                if owner_count < 2:
                    # There must be at least one owner
                    ErrorDialog(_('Error'),
                                _('A Group Chat needs at least one Owner'))
                    return
                owner_count -= 1
            references.append(Gtk.TreeRowReference.new(model, path))

        for ref in references:
            iter_ = model.get_iter(ref.get_path())
            model.remove(iter_)

    def _on_jid_edited(self, _renderer, path, new_text):
        old_text = self._ui.affiliation_store[path][MUCUser.JID]
        if new_text == old_text:
            return

        if self._jid_exists(new_text):
            self._raise_error()
            return

        self._ui.affiliation_store[path][MUCUser.JID] = new_text

    def _on_outcast_jid_edited(self, _renderer, path, new_text):
        old_text = self._ui.outcast_store[path][MUCUser.JID]
        if new_text == old_text:
            return

        if self._jid_exists(new_text):
            self._raise_error()
            return

        self._ui.outcast_store[path][MUCUser.JID] = new_text
        self._ui.outcast_store[path][MUCUser.AFFILIATION] = 'outcast'

    def _on_nick_edited(self, _renderer, path, new_text):
        self._ui.affiliation_store[path][MUCUser.NICK] = new_text

    def _on_reason_edited(self, _renderer, path, new_text):
        self._ui.outcast_store[path][MUCUser.REASON] = new_text

    def _on_affiliation_changed(self, cell_renderer_combo,
                                path_string, new_iter):
        combo_store = cell_renderer_combo.get_property('model')
        affiliation_text = combo_store.get_value(new_iter, 0)
        affiliation = combo_store.get_value(new_iter, 1)

        store = self._ui.affiliation_treeview.get_model()

        store[path_string][MUCUser.AFFILIATION] = affiliation
        store[path_string][MUCUser.AFFILIATION_TEXT] = affiliation_text

    def _on_selection_changed(self, tree_selection):
        sensitive = bool(tree_selection.count_selected_rows())
        selected_affiliations = self._get_selected_affiliations(tree_selection)
        self._set_remove_button_state(sensitive, selected_affiliations)

    def _jid_exists(self, jid):
        stores = [self._ui.affiliation_store, self._ui.outcast_store]

        for store in stores:
            for row in store:
                if row[MUCUser.JID] == jid:
                    return True
        return False

    @staticmethod
    def _get_selected_affiliations(tree_selection):
        model, paths = tree_selection.get_selected_rows()
        selected_affiliations = set()
        for path in paths:
            selected_affiliations.add(model[path][MUCUser.AFFILIATION])
        return selected_affiliations

    def _on_switch_page(self, stack, _pspec):
        page_name = stack.get_visible_child_name()
        self._set_button_box_state(page_name)
        if page_name == 'config':
            return

        treeview = getattr(self._ui, '%s_treeview' % page_name)
        sensitive = bool(treeview.get_selection().count_selected_rows())

        selected_affiliations = self._get_selected_affiliations(
            treeview.get_selection())
        self._set_remove_button_state(sensitive, selected_affiliations)

    def _set_button_box_state(self, page_name):
        affiliation = self._own_affiliation in ('admin', 'owner')
        page = page_name != 'config'
        self._ui.treeview_buttonbox.set_visible(affiliation and page)
        self._ui.info_button.set_sensitive(page_name == 'outcast')

    def _set_remove_button_state(self, sensitive, selected_affiliations):
        if self._own_affiliation not in ('admin', 'owner'):
            self._ui.remove_button.set_sensitive(False)
            return

        self._ui.remove_button.set_tooltip_text('')

        if not sensitive:
            self._ui.remove_button.set_sensitive(False)
            return

        if self._own_affiliation == 'owner':
            self._ui.remove_button.set_sensitive(True)
            return

        if set(['owner', 'admin']).intersection(selected_affiliations):
            self._ui.remove_button.set_sensitive(False)
            self._ui.remove_button.set_tooltip_text(
                _('You are not allowed to modify the affiliation '
                  'of Admins and Owners'))
            return

        self._ui.remove_button.set_sensitive(True)

    def _get_owner_count(self):
        owner_count = 0
        for row in self._ui.affiliation_store:
            if row[MUCUser.AFFILIATION] == 'owner':
                owner_count += 1
        return owner_count

    def _allowed_to_edit(self, affiliation):
        if self._own_affiliation == 'owner':
            return True, True

        if self._own_affiliation == 'admin':
            if affiliation in ('admin', 'owner'):
                return False, False
            return False, True
        return False, False

    def _on_ok(self, *args):
        if self._own_affiliation in ('admin', 'owner'):
            self._set_affiliations()

        if self._form is not None and self._own_affiliation == 'owner':
            form = self._data_form_widget.get_submit_form()
            con = app.connections[self.account]
            con.get_module('MUC').set_config(self.jid, form)
        self.destroy()

    def _get_diff(self):
        stores = [self._ui.affiliation_store, self._ui.outcast_store]

        self._new_affiliations = {}
        for store in stores:
            for row in store:
                if not row[MUCUser.JID]:
                    # Ignore empty JID field
                    continue

                attr = 'nick'
                if row[MUCUser.AFFILIATION] == 'outcast':
                    attr = 'reason'

                self._new_affiliations[row[MUCUser.JID]] = {
                    'affiliation': row[MUCUser.AFFILIATION],
                    attr: row[MUCUser.NICK_OR_REASON]}

        old_jids = set(self._affiliations.keys())
        new_jids = set(self._new_affiliations.keys())
        remove = old_jids - new_jids
        add = new_jids - old_jids
        modified = new_jids - remove - add

        return add, remove, modified

    def _on_key_press(self, _widget, event):
        if event.keyval == Gdk.KEY_Escape:
            self._on_cancel()

    def _on_cancel(self, *args):
        self._cancel()
        self.destroy()

    def _cancel(self, *args):
        if self._form and self._own_affiliation == 'owner':
            con = app.connections[self.account]
            con.get_module('MUC').cancel_config(self.jid)

    def _on_destroy(self, *args):
        self._destroyed = True

    def _set_affiliations(self):
        add, remove, modified = self._get_diff()

        diff_dict = {}
        for jid in add:
            diff_dict[jid] = self._new_affiliations[jid]

        for jid in remove:
            diff_dict[jid] = {'affiliation': 'none'}

        for jid in modified:
            if self._new_affiliations[jid] == self._affiliations[jid]:
                # Not modified
                continue

            diff_dict[jid] = self._new_affiliations[jid]
            if self._new_affiliations[jid]['affiliation'] == 'outcast':
                # New affiliation is outcast, check if the reason changed.
                # In case the affiliation was 'admin', 'owner' or 'member'
                # before, there is no reason.
                new_reason = self._new_affiliations[jid]['reason']
                old_reason = self._affiliations[jid].get('reason')
                if new_reason == old_reason:
                    diff_dict[jid].pop('reason', None)

            else:
                # New affiliation is not outcast, check if the nick has changed.
                # In case the affiliation was 'outcast' there is no nick.
                new_nick = self._new_affiliations[jid]['nick']
                old_nick = self._affiliations[jid].get('nick')
                if new_nick == old_nick:
                    diff_dict[jid].pop('nick', None)

        if not diff_dict:
            # No changes were made
            return
        con = app.connections[self.account]
        con.get_module('MUC').set_affiliation(self.jid, diff_dict)

    @ensure_not_destroyed
    def _on_affiliations_received(self, result, affiliation):
        if is_error_result(result):
            log.info('Error while requesting %s affiliations: %s',
                     affiliation, result)
            return

        if affiliation == 'outcast':
            self._ui.stack.get_child_by_name('outcast').show()

        for jid, attrs in result.users.items():
            affiliation_edit, jid_edit = self._allowed_to_edit(affiliation)
            if affiliation == 'outcast':
                reason = attrs.get('reason')
                self._ui.outcast_store.append(
                    [str(jid),
                     reason,
                     None,
                     affiliation,
                     None,
                     affiliation_edit,
                     jid_edit])
                self._affiliations[jid] = {'affiliation': affiliation,
                                           'reason': reason}
            else:
                nick = attrs.get('nick')
                role = attrs.get('role')
                self._ui.affiliation_store.append(
                    [str(jid),
                     nick,
                     role,
                     affiliation,
                     _(affiliation.capitalize()),
                     affiliation_edit,
                     jid_edit])
                self._affiliations[jid] = {'affiliation': affiliation,
                                           'nick': nick}
                if role is not None:
                    self._ui.role_column.set_visible(True)

    @staticmethod
    def _raise_error():
        ErrorDialog(_('Error'),
                    _('An entry with this XMPP Address already exists'))
Ejemplo n.º 15
0
class ServiceRegistration(Gtk.Assistant):
    def __init__(self, account, agent):
        Gtk.Assistant.__init__(self)

        self._con = app.connections[account]
        self._agent = agent
        self._account = account
        self._data_form_widget = None
        self._is_form = None

        self.set_application(app.app)
        self.set_resizable(True)
        self.set_position(Gtk.WindowPosition.CENTER)

        self.set_default_size(600, 400)
        self.get_style_context().add_class('dialog-margin')

        self._add_page(RequestPage())
        self._add_page(FormPage())
        self._add_page(SendingPage())
        self._add_page(SuccessfulPage())
        self._add_page(ErrorPage())

        self.connect('prepare', self._on_page_change)
        self.connect('cancel', self._on_cancel)
        self.connect('close', self._on_cancel)

        self._remove_sidebar()
        self.show_all()

    def _add_page(self, page):
        self.append_page(page)
        self.set_page_type(page, page.type_)
        self.set_page_title(page, page.title)
        self.set_page_complete(page, page.complete)

    def _remove_sidebar(self):
        main_box = self.get_children()[0]
        sidebar = main_box.get_children()[0]
        main_box.remove(sidebar)

    def _on_page_change(self, assistant, page):
        if self.get_current_page() == Page.REQUEST:
            self._con.get_module('Register').get_register_form(
                self._agent, self._on_get_success, self._on_error)
        elif self.get_current_page() == Page.SENDING:
            self._register()
            self.commit()
            pass

    def _on_get_success(self, form, is_form):
        log.info('Show Form page')
        self._is_form = is_form
        if is_form:
            dataform = dataforms.ExtendForm(node=form)
            self._data_form_widget = DataFormWidget(dataform)
        else:
            from gajim import config
            self._data_form_widget = config.FakeDataForm(form)

        page = self.get_nth_page(Page.FORM)
        page.pack_start(self._data_form_widget, True, True, 0)
        self._data_form_widget.show_all()
        self.set_current_page(Page.FORM)

    def _on_error(self, error_text):
        log.info('Show Error page')
        page = self.get_nth_page(Page.ERROR)
        page.set_text(error_text)
        self.set_current_page(Page.ERROR)

    def _on_cancel(self, widget):
        self.destroy()

    def _register(self):
        log.info('Show Sending page')
        if self._is_form:
            form = self._data_form_widget.get_submit_form()
        else:
            form = self._data_form_widget.get_infos()
            if 'instructions' in form:
                del form['instructions']
            if 'registered' in form:
                del form['registered']

        self._con.get_module('Register').register_agent(
            self._agent, form, self._is_form, self._on_register_success,
            self._on_error)

    def _on_register_success(self):
        log.info('Show Success page')
        self.set_current_page(Page.SUCCESS)
Ejemplo n.º 16
0
class Completed(Gtk.Box):

    type_ = Gtk.AssistantPageType.CUSTOM
    title = _('Finished')
    complete = True

    def __init__(self):
        super().__init__(orientation=Gtk.Orientation.VERTICAL)
        self.set_spacing(12)
        self._notes = []
        self._dataform_widget = None

        icon = Gtk.Image.new_from_icon_name('object-select-symbolic',
                                            Gtk.IconSize.DIALOG)
        icon.get_style_context().add_class('success-color')
        icon.show()

        label = Gtk.Label(label='Finished')
        label.show()

        self._icon_text = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
        self._icon_text.set_spacing(12)
        self._icon_text.set_halign(Gtk.Align.CENTER)
        self._icon_text.add(icon)
        self._icon_text.add(label)
        self.add(self._icon_text)

        self.show_all()

    def process_stage(self, stage_data):
        self._show_notes(stage_data.notes)
        self._show_form(stage_data.data)
        self._show_icon_text(stage_data.data is None)

    def _show_icon_text(self, show):
        if show:
            self.set_valign(Gtk.Align.CENTER)
            self._icon_text.show_all()
        else:
            self.set_valign(Gtk.Align.FILL)
            self._icon_text.hide()

    def _show_form(self, form):
        if self._dataform_widget is not None:
            self.remove(self._dataform_widget)
            self._dataform_widget.destroy()
        if form is None:
            return

        form = dataforms.extend_form(node=form)

        self._dataform_widget = DataFormWidget(form,
                                               options={'read-only': True})
        self._dataform_widget.show_all()
        self.add(self._dataform_widget)

    def _show_notes(self, notes):
        for note in self._notes:
            self.remove(note)
        self._notes = []

        for note in notes:
            label = MultiLineLabel(label=note.text)
            label.set_justify(Gtk.Justification.CENTER)
            label.show()
            self._notes.append(label)
            self.add(label)
Ejemplo n.º 17
0
class Stage(Gtk.Box):

    type_ = Gtk.AssistantPageType.CUSTOM
    title = _('Settings')
    complete = True

    def __init__(self):
        super().__init__(orientation=Gtk.Orientation.VERTICAL)
        self.set_spacing(18)
        self._dataform_widget = None
        self._notes = []
        self._last_stage_data = None
        self.show_all()

    @property
    def stage_data(self):
        return self._last_stage_data, self._dataform_widget.get_submit_form()

    @property
    def actions(self):
        return self._last_stage_data.actions

    def clear(self):
        self._show_form(None)
        self._show_notes(None)
        self._last_stage_data = None

    def process_stage(self, stage_data):
        self._last_stage_data = stage_data
        self._show_notes(stage_data.notes)
        self._show_form(stage_data.data)

    def _show_form(self, form):
        if self._dataform_widget is not None:
            self.remove(self._dataform_widget)
            self._dataform_widget.destroy()
        if form is None:
            return
        form = dataforms.extend_form(node=form)
        self._dataform_widget = DataFormWidget(form)
        self._dataform_widget.connect('is-valid', self._on_is_valid)
        self._dataform_widget.validate()
        self._dataform_widget.show_all()
        self.add(self._dataform_widget)

    def _show_notes(self, notes):
        for note in self._notes:
            self.remove(note)
        self._notes = []

        if notes is None:
            return

        for note in notes:
            label = Gtk.Label(label=note.text)
            label.show()
            self._notes.append(label)
            self.add(label)

    def _on_is_valid(self, _widget, is_valid):
        self.get_toplevel().set_stage_complete(is_valid)