Daniel Brötzmann pushed to branch mainwindow at gajim / gajim

Commits:

6 changed files:

Changes:

  • gajim/chat_control.py
    ... ... @@ -397,34 +397,10 @@ def _on_add_to_roster(self, _action, _param):
    397 397
             AddNewContactWindow(self.account, self.contact.jid)
    
    398 398
     
    
    399 399
         def _on_block_contact(self, _action, _param):
    
    400
    -        def _block_contact(report=None):
    
    401
    -            con = app.connections[self.account]
    
    402
    -            con.get_module('Blocking').block([self.contact.jid], report=report)
    
    403
    -
    
    404
    -            self.parent_win.remove_tab(self, None, force=True)
    
    405
    -            if _('Not in contact list') in self.contact.get_shown_groups():
    
    406
    -                app.interface.roster.remove_contact(
    
    407
    -                    self.contact.jid, self.account, force=True, backend=True)
    
    408
    -                return
    
    409
    -            app.interface.roster.draw_contact(self.contact.jid, self.account)
    
    410
    -
    
    411
    -        ConfirmationDialog(
    
    412
    -            _('Block Contact'),
    
    413
    -            _('Really block this contact?'),
    
    414
    -            _('You will appear offline for this contact and you will '
    
    415
    -              'not receive further messages.'),
    
    416
    -            [DialogButton.make('Cancel'),
    
    417
    -             DialogButton.make('OK',
    
    418
    -                               text=_('_Report Spam'),
    
    419
    -                               callback=_block_contact,
    
    420
    -                               kwargs={'report': 'spam'}),
    
    421
    -             DialogButton.make('Remove',
    
    422
    -                               text=_('_Block'),
    
    423
    -                               callback=_block_contact)],
    
    424
    -            modal=False).show()
    
    400
    +        app.window.block_contact(self.account, self.contact.jid)
    
    425 401
     
    
    426 402
         def _on_information(self, _action, _param):
    
    427
    -        app.interface.roster.on_info(None, self.contact, self.account)
    
    403
    +        app.window.contact_info(self.account, self.contact.jid)
    
    428 404
     
    
    429 405
         def _on_invite_contacts(self, _action, _param):
    
    430 406
             """
    

  • gajim/gtk/account_page.py
    ... ... @@ -37,6 +37,9 @@ def __init__(self, account):
    37 37
             self._roster = Roster(account)
    
    38 38
             self._ui.roster_box.add(self._roster)
    
    39 39
     
    
    40
    +        self._ui.paned.set_position(app.settings.get('chat_handle_position'))
    
    41
    +        self._ui.paned.connect('button-release-event', self._on_button_release)
    
    42
    +
    
    40 43
             self._ui.connect_signals(self)
    
    41 44
             self.show_all()
    
    42 45
     
    
    ... ... @@ -46,6 +49,16 @@ def _on_account_settings(self, _button):
    46 49
             window = open_window('AccountsWindow')
    
    47 50
             window.select_account(self._account)
    
    48 51
     
    
    52
    +    @staticmethod
    
    53
    +    def _on_button_release(paned, event):
    
    54
    +        if event.window != paned.get_handle_window():
    
    55
    +            return
    
    56
    +        position = paned.get_position()
    
    57
    +        app.settings.set('chat_handle_position', position)
    
    58
    +
    
    59
    +    def get_roster(self):
    
    60
    +        return self._roster
    
    61
    +
    
    49 62
         def update(self):
    
    50 63
             account_label = app.settings.get_account_setting(
    
    51 64
                 self._account, 'account_label')
    

  • gajim/gtk/chat_list.py
    ... ... @@ -418,7 +418,9 @@ def _on_state_flags_changed(self, _listboxrow, *args):
    418 418
                 self._ui.revealer.set_reveal_child(False)
    
    419 419
     
    
    420 420
         def _on_close_button_clicked(self, _button):
    
    421
    -        app.window.remove_chat(self.workspace_id, self.account, self.jid)
    
    421
    +        app.window.activate_action(
    
    422
    +            'remove-chat',
    
    423
    +            GLib.Variant('as', [self.account, self.jid]))
    
    422 424
     
    
    423 425
         def set_timestamp(self, timestamp):
    
    424 426
             self._timestamp = timestamp
    

  • gajim/gtk/main.py
    ... ... @@ -7,20 +7,23 @@
    7 7
     
    
    8 8
     from gajim.common import app
    
    9 9
     from gajim.common import ged
    
    10
    +from gajim.common.helpers import ask_for_status_message
    
    11
    +from gajim.common.helpers import jid_is_blocked
    
    10 12
     from gajim.common.i18n import _
    
    11
    -from gajim.gui.util import get_builder
    
    12
    -from gajim.gui.util import load_icon
    
    13
    +from gajim.common.nec import EventHelper
    
    14
    +
    
    13 15
     from gajim.gui.account_page import AccountPage
    
    16
    +from gajim.gui.adhoc import AdHocCommand
    
    14 17
     from gajim.gui.chat_list_stack import ChatListStack
    
    15 18
     from gajim.gui.chat_stack import ChatStack
    
    16 19
     from gajim.gui.account_side_bar import AccountSideBar
    
    17 20
     from gajim.gui.workspace_side_bar import WorkspaceSideBar
    
    18
    -
    
    19
    -from gajim.common.helpers import ask_for_status_message
    
    20 21
     from gajim.gui.dialogs import DialogButton
    
    21 22
     from gajim.gui.dialogs import ConfirmationDialog
    
    23
    +from gajim.gui.util import get_builder
    
    24
    +from gajim.gui.util import load_icon
    
    22 25
     
    
    23
    -from gajim.common.nec import EventHelper
    
    26
    +from gajim.vcard import VcardWindow
    
    24 27
     
    
    25 28
     from .util import open_window
    
    26 29
     
    
    ... ... @@ -425,11 +428,14 @@ def move_chat_to_workspace(self, new_workspace_id, account, jid):
    425 428
             self._chat_list_stack.store_open_chats(new_workspace_id)
    
    426 429
     
    
    427 430
         def _remove_chat(self, _action, param):
    
    428
    -        workspace_id, account, jid = param.unpack()
    
    429
    -        self.remove_chat(workspace_id, account, jid)
    
    431
    +        account, jid = param.unpack()
    
    432
    +        self.remove_chat(account, jid)
    
    430 433
     
    
    431
    -    def remove_chat(self, workspace_id, account, jid):
    
    432
    -        self._chat_list_stack.remove_chat(workspace_id, account, jid)
    
    434
    +    def remove_chat(self, account, jid):
    
    435
    +        for workspace_id in app.settings.get_workspaces():
    
    436
    +            if self.chat_exists_for_workspace(workspace_id, account, jid):
    
    437
    +                self._chat_list_stack.remove_chat(workspace_id, account, jid)
    
    438
    +                return
    
    433 439
     
    
    434 440
         def chat_exists(self, account, jid):
    
    435 441
             return self._chat_list_stack.contains_chat(account, jid)
    
    ... ... @@ -447,14 +453,91 @@ def get_active_control(self):
    447 453
                 return None
    
    448 454
             return self.get_control(chat.account, chat.jid)
    
    449 455
     
    
    456
    +    def get_controls(self, account=None):
    
    457
    +        return self._chat_stack.get_controls(account)
    
    458
    +
    
    450 459
         def _add_accounts(self):
    
    451 460
             for account in list(app.connections.keys()):
    
    452 461
                 account_page = AccountPage(account)
    
    453 462
                 self._account_pages[account] = account_page
    
    454 463
                 self._ui.main_stack.add_named(account_page, account)
    
    455 464
     
    
    456
    -    def get_controls(self, account=None):
    
    457
    -        return self._chat_stack.get_controls(account)
    
    465
    +    @staticmethod
    
    466
    +    def contact_info(account, jid):
    
    467
    +        client = app.get_client(account)
    
    468
    +        contact = client.get_module('Contacts').get_contact(jid)
    
    469
    +
    
    470
    +        # TODO: VcardWindow does not work with new type Contacts
    
    471
    +        info = app.interface.instances[account]['infos']
    
    472
    +        if contact.jid in info:
    
    473
    +            info[contact.jid].window.present()
    
    474
    +        else:
    
    475
    +            info[contact.jid] = VcardWindow(contact, account)
    
    476
    +
    
    477
    +    @staticmethod
    
    478
    +    def execute_command(account, jid):
    
    479
    +        # TODO: Resource?
    
    480
    +        AdHocCommand(account, jid)
    
    481
    +
    
    482
    +    def block_contact(self, account, jid):
    
    483
    +        client = app.get_client(account)
    
    484
    +
    
    485
    +        if jid_is_blocked(account, jid):
    
    486
    +            client.get_module('Blocking').unblock([jid])
    
    487
    +            roster = self._account_pages[account].get_roster()
    
    488
    +            roster.draw_contact(jid)
    
    489
    +            return
    
    490
    +
    
    491
    +        # TODO: Keep "confirm_block" setting?
    
    492
    +        def _block_contact(report=None):
    
    493
    +            app.events.remove_events(account, jid)
    
    494
    +
    
    495
    +            contact = client.get_module('Contacts').get_contact(jid)
    
    496
    +            client.get_module('Blocking').block([jid], report)
    
    497
    +            if not contact.is_in_roster:
    
    498
    +                self.remove_chat(account, jid)
    
    499
    +                return
    
    500
    +
    
    501
    +            roster = self._account_pages[account].get_roster()
    
    502
    +            roster.draw_contact(jid)
    
    503
    +            # TODO: draw_contact draws too early (not blocked yet)
    
    504
    +            # TODO: Draw ChatList row differently?
    
    505
    +
    
    506
    +        ConfirmationDialog(
    
    507
    +            _('Block Contact'),
    
    508
    +            _('Really block this contact?'),
    
    509
    +            _('You will appear offline for this contact and you '
    
    510
    +              'will not receive further messages.'),
    
    511
    +            [DialogButton.make('Cancel'),
    
    512
    +             DialogButton.make('OK',
    
    513
    +                               text=_('_Report Spam'),
    
    514
    +                               callback=_block_contact,
    
    515
    +                               kwargs={'report': 'spam'}),
    
    516
    +             DialogButton.make('Remove',
    
    517
    +                               text=_('_Block'),
    
    518
    +                               callback=_block_contact)],
    
    519
    +            modal=False).show()
    
    520
    +
    
    521
    +    def remove_contact(self, account, jid):
    
    522
    +        def _remove_contact():
    
    523
    +            self.remove_chat(account, jid)
    
    524
    +            roster = self._account_pages[account].get_roster()
    
    525
    +            roster.remove_contact(jid)
    
    526
    +
    
    527
    +        client = app.get_client(account)
    
    528
    +        contact = client.get_module('Contacts').get_contact(jid)
    
    529
    +        sec_text = _('You are about to remove %(name)s (%(jid)s) from '
    
    530
    +                     'your contact list.\n') % {
    
    531
    +                         'name': contact.name,
    
    532
    +                         'jid': jid}
    
    533
    +        # TODO: ConfirmationCheckDialog for subscription decision?
    
    534
    +        ConfirmationDialog(
    
    535
    +            _('Remove Contact'),
    
    536
    +            _('Remove contact from contact list'),
    
    537
    +            sec_text,
    
    538
    +            [DialogButton.make('Cancel'),
    
    539
    +             DialogButton.make('Remove',
    
    540
    +                               callback=_remove_contact)]).show()
    
    458 541
     
    
    459 542
         def _load_chats(self):
    
    460 543
             for workspace_id in app.settings.get_workspaces():
    

  • gajim/gtk/roster.py
    ... ... @@ -4,6 +4,7 @@
    4 4
     from enum import IntEnum
    
    5 5
     
    
    6 6
     from gi.repository import Gdk
    
    7
    +from gi.repository import Gio
    
    7 8
     from gi.repository import GLib
    
    8 9
     from gi.repository import Gtk
    
    9 10
     from gi.repository import GObject
    
    ... ... @@ -12,6 +13,7 @@
    12 13
     from gajim.common import ged
    
    13 14
     from gajim.common.const import AvatarSize
    
    14 15
     from gajim.common.const import StyleAttr
    
    16
    +from gajim.common.helpers import jid_is_blocked
    
    15 17
     from gajim.common.i18n import _
    
    16 18
     
    
    17 19
     from gajim.gui_menu_builder import get_roster_menu
    
    ... ... @@ -73,11 +75,70 @@ def __init__(self, account):
    73 75
             self._ui.connect_signals(self)
    
    74 76
     
    
    75 77
             self.register_events([
    
    78
    +            ('account-connected', ged.CORE, self._on_account_state),
    
    79
    +            ('account-disconnected', ged.CORE, self._on_account_state),
    
    76 80
                 ('theme-update', ged.GUI2, self._on_theme_update),
    
    77 81
             ])
    
    78 82
     
    
    83
    +        self._add_actions()
    
    79 84
             self._initial_draw()
    
    80 85
     
    
    86
    +    def _add_actions(self):
    
    87
    +        actions = [
    
    88
    +            ('contact-info', self._contact_info),
    
    89
    +            ('execute-command', self._execute_command),
    
    90
    +            ('block-contact', self._block_contact),
    
    91
    +            ('remove-contact', self._remove_contact),
    
    92
    +        ]
    
    93
    +        for action in actions:
    
    94
    +            action_name, func = action
    
    95
    +            act = Gio.SimpleAction.new(
    
    96
    +                f'{action_name}-{self._account}', GLib.VariantType.new('s'))
    
    97
    +            act.connect('activate', func)
    
    98
    +            app.window.add_action(act)
    
    99
    +
    
    100
    +    def update_actions(self):
    
    101
    +        online = app.account_is_connected(self._account)
    
    102
    +        blocking_support = self._client.get_module('Blocking').supported
    
    103
    +
    
    104
    +        app.window.lookup_action(
    
    105
    +            f'contact-info-{self._account}').set_enabled(online)
    
    106
    +        app.window.lookup_action(
    
    107
    +            f'execute-command-{self._account}').set_enabled(online)
    
    108
    +        app.window.lookup_action(
    
    109
    +            f'block-contact-{self._account}').set_enabled(
    
    110
    +                online and blocking_support)
    
    111
    +        app.window.lookup_action(
    
    112
    +            f'remove-contact-{self._account}').set_enabled(online)
    
    113
    +
    
    114
    +    def _remove_actions(self):
    
    115
    +        actions = [
    
    116
    +            'contact-info',
    
    117
    +            'execute-command',
    
    118
    +            'block-contact',
    
    119
    +            'remove-contact',
    
    120
    +        ]
    
    121
    +        for action in actions:
    
    122
    +            app.window.remove_action(f'{action}-{self._account}')
    
    123
    +
    
    124
    +    def _on_account_state(self, _event):
    
    125
    +        self.update_actions()
    
    126
    +
    
    127
    +    def _on_theme_update(self, _event):
    
    128
    +        self.redraw()
    
    129
    +
    
    130
    +    def _contact_info(self, _action, param):
    
    131
    +        app.window.contact_info(self._account, param.get_string())
    
    132
    +
    
    133
    +    def _execute_command(self, _action, param):
    
    134
    +        app.window.execute_command(self._account, param.get_string())
    
    135
    +
    
    136
    +    def _block_contact(self, _action, param):
    
    137
    +        app.window.block_contact(self._account, param.get_string())
    
    138
    +
    
    139
    +    def _remove_contact(self, _action, param):
    
    140
    +        app.window.remove_contact(self._account, param.get_string())
    
    141
    +
    
    81 142
         def _on_roster_row_activated(self, _treeview, path, _column):
    
    82 143
             iter_ = self._store.get_iter(path)
    
    83 144
             if self._store.iter_parent(iter_) is None:
    
    ... ... @@ -113,9 +174,6 @@ def _on_roster_button_press_event(self, treeview, event):
    113 174
         def _on_focus_out(treeview, _param):
    
    114 175
             treeview.get_selection().unselect_all()
    
    115 176
     
    
    116
    -    def _on_theme_update(self, _event):
    
    117
    -        self.redraw()
    
    118
    -
    
    119 177
         def _show_contact_menu(self, jid, treeview, event):
    
    120 178
             menu = get_roster_menu(self._account, jid)
    
    121 179
     
    
    ... ... @@ -131,6 +189,7 @@ def _show_contact_menu(self, jid, treeview, event):
    131 189
             popover.popup()
    
    132 190
     
    
    133 191
         def _on_destroy(self, _roster):
    
    192
    +        self._remove_actions()
    
    134 193
             self._contact_refs = {}
    
    135 194
             self._group_refs = {}
    
    136 195
             self._roster.set_model(None)
    
    ... ... @@ -163,8 +222,7 @@ def invalidate_sort(self):
    163 222
             self.enable_sort(True)
    
    164 223
     
    
    165 224
         def _initial_draw(self):
    
    166
    -        client = app.get_client(self._account)
    
    167
    -        for contact in client.get_module('Roster').iter_contacts():
    
    225
    +        for contact in self._client.get_module('Roster').iter_contacts():
    
    168 226
                 contact.connect('presence-update', self._on_presence_update)
    
    169 227
                 contact.connect('avatar-update', self._on_avatar_update)
    
    170 228
                 self._add_contact(contact)
    
    ... ... @@ -217,6 +275,27 @@ def _add_contact(self, contact):
    217 275
                     self._roster.get_model() is not None):
    
    218 276
                 self._roster.expand_row(group_path, False)
    
    219 277
     
    
    278
    +    def remove_contact(self, jid):
    
    279
    +        # TODO: How to delete a roster item?
    
    280
    +        #self._client.get_module('Roster').delete_item(jid)
    
    281
    +
    
    282
    +        iter_ = self._get_contact_iter(jid)
    
    283
    +        if not iter_:
    
    284
    +            return
    
    285
    +
    
    286
    +        group_iter = self._store.iter_parent(iter_)
    
    287
    +        if group_iter is None:
    
    288
    +            raise ValueError('Trying to remove non-chil')
    
    289
    +
    
    290
    +        self._store.remove(iter_)
    
    291
    +        del self._contact_refs[jid]
    
    292
    +        if not self._store.iter_has_child(group_iter):
    
    293
    +            group = self._store[group_iter][Column.JID_OR_GROUP]
    
    294
    +            del self._group_refs[group]
    
    295
    +            self._store.remove(group_iter)
    
    296
    +
    
    297
    +        self.redraw()
    
    298
    +
    
    220 299
         def draw_groups(self):
    
    221 300
             for group in self._group_refs:
    
    222 301
                 self.draw_group(group)
    
    ... ... @@ -242,9 +321,12 @@ def draw_contact(self, jid):
    242 321
                 return
    
    243 322
     
    
    244 323
             contact = self._client.get_module('Contacts').get_contact(jid)
    
    324
    +        name = GLib.markup_escape_text(contact.name)
    
    325
    +        if jid_is_blocked(self._account, jid):
    
    326
    +            name = f'<span strikethrough="true">{name}</span>'
    
    245 327
     
    
    246 328
             self.draw_avatar(contact)
    
    247
    -        self._store[iter_][Column.TEXT] = GLib.markup_escape_text(contact.name)
    
    329
    +        self._store[iter_][Column.TEXT] = name
    
    248 330
     
    
    249 331
         def draw_avatar(self, contact):
    
    250 332
             iter_ = self._get_contact_iter(str(contact.jid))
    

  • gajim/gui_menu_builder.py
    ... ... @@ -797,17 +797,24 @@ def get_conv_context_menu(account, uri):
    797 797
     
    
    798 798
     
    
    799 799
     def get_roster_menu(account, jid):
    
    800
    +    if helpers.jid_is_blocked(account, jid):
    
    801
    +        block_label = _('Unblock')
    
    802
    +    else:
    
    803
    +        block_label = _('Block…')
    
    800 804
         menu_items = [
    
    801
    -        ('show-contact-info', _('Contact Info')),
    
    805
    +        ('contact-info', _('Information')),
    
    806
    +        ('execute-command', _('Execute Command…')),
    
    807
    +        ('block-contact', block_label),
    
    808
    +        ('remove-contact', _('Remove…')),
    
    802 809
         ]
    
    810
    +
    
    803 811
         menu = Gio.Menu()
    
    804 812
         for item in menu_items:
    
    805 813
             action, label = item
    
    806
    -        action = f'win.{action}'
    
    814
    +        action = f'win.{action}-{account}'
    
    807 815
             menuitem = Gio.MenuItem.new(label, action)
    
    808
    -        variant_list = GLib.Variant(
    
    809
    -            'as', [account, str(jid)])
    
    810
    -        menuitem.set_action_and_target_value(action, variant_list)
    
    816
    +        variant = GLib.Variant('s', str(jid))
    
    817
    +        menuitem.set_action_and_target_value(action, variant)
    
    811 818
             menu.append_item(menuitem)
    
    812 819
     
    
    813 820
         return menu