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

Commits:

8 changed files:

Changes:

  • gajim/data/gui/account_page.ui
    1
    +<?xml version="1.0" encoding="UTF-8"?>
    
    2
    +<!-- Generated with glade 3.38.2 -->
    
    3
    +<interface>
    
    4
    +  <requires lib="gtk+" version="3.24"/>
    
    5
    +  <object class="GtkPaned" id="paned">
    
    6
    +    <property name="visible">True</property>
    
    7
    +    <property name="can-focus">True</property>
    
    8
    +    <child>
    
    9
    +      <object class="GtkBox" id="roster_box">
    
    10
    +        <property name="visible">True</property>
    
    11
    +        <property name="can-focus">False</property>
    
    12
    +        <property name="orientation">vertical</property>
    
    13
    +        <property name="spacing">6</property>
    
    14
    +        <child>
    
    15
    +          <object class="GtkBox">
    
    16
    +            <property name="visible">True</property>
    
    17
    +            <property name="can-focus">False</property>
    
    18
    +            <property name="orientation">vertical</property>
    
    19
    +            <property name="spacing">3</property>
    
    20
    +            <child>
    
    21
    +              <object class="GtkBox">
    
    22
    +                <property name="visible">True</property>
    
    23
    +                <property name="can-focus">False</property>
    
    24
    +                <property name="spacing">12</property>
    
    25
    +                <child>
    
    26
    +                  <object class="GtkLabel">
    
    27
    +                    <property name="visible">True</property>
    
    28
    +                    <property name="can-focus">False</property>
    
    29
    +                    <property name="halign">start</property>
    
    30
    +                    <property name="label" translatable="yes">Contact List</property>
    
    31
    +                    <style>
    
    32
    +                      <class name="bold16"/>
    
    33
    +                    </style>
    
    34
    +                  </object>
    
    35
    +                  <packing>
    
    36
    +                    <property name="expand">True</property>
    
    37
    +                    <property name="fill">True</property>
    
    38
    +                    <property name="position">0</property>
    
    39
    +                  </packing>
    
    40
    +                </child>
    
    41
    +                <child>
    
    42
    +                  <object class="GtkMenuButton" id="roster_menu_button">
    
    43
    +                    <property name="visible">True</property>
    
    44
    +                    <property name="can-focus">True</property>
    
    45
    +                    <property name="focus-on-click">False</property>
    
    46
    +                    <property name="receives-default">True</property>
    
    47
    +                    <property name="halign">end</property>
    
    48
    +                    <child>
    
    49
    +                      <object class="GtkImage">
    
    50
    +                        <property name="visible">True</property>
    
    51
    +                        <property name="can-focus">False</property>
    
    52
    +                        <property name="icon-name">open-menu-symbolic</property>
    
    53
    +                      </object>
    
    54
    +                    </child>
    
    55
    +                  </object>
    
    56
    +                  <packing>
    
    57
    +                    <property name="expand">False</property>
    
    58
    +                    <property name="fill">True</property>
    
    59
    +                    <property name="pack-type">end</property>
    
    60
    +                    <property name="position">1</property>
    
    61
    +                  </packing>
    
    62
    +                </child>
    
    63
    +              </object>
    
    64
    +              <packing>
    
    65
    +                <property name="expand">False</property>
    
    66
    +                <property name="fill">True</property>
    
    67
    +                <property name="position">0</property>
    
    68
    +              </packing>
    
    69
    +            </child>
    
    70
    +            <child>
    
    71
    +              <object class="GtkSearchEntry" id="roster_search_entry">
    
    72
    +                <property name="visible">True</property>
    
    73
    +                <property name="can-focus">True</property>
    
    74
    +                <property name="primary-icon-name">edit-find-symbolic</property>
    
    75
    +                <property name="primary-icon-activatable">False</property>
    
    76
    +                <property name="primary-icon-sensitive">False</property>
    
    77
    +                <property name="placeholder-text" translatable="yes">Search…</property>
    
    78
    +              </object>
    
    79
    +              <packing>
    
    80
    +                <property name="expand">False</property>
    
    81
    +                <property name="fill">True</property>
    
    82
    +                <property name="position">1</property>
    
    83
    +              </packing>
    
    84
    +            </child>
    
    85
    +            <child>
    
    86
    +              <object class="GtkSeparator">
    
    87
    +                <property name="visible">True</property>
    
    88
    +                <property name="can-focus">False</property>
    
    89
    +                <property name="margin-start">6</property>
    
    90
    +                <property name="margin-end">6</property>
    
    91
    +                <property name="margin-top">12</property>
    
    92
    +              </object>
    
    93
    +              <packing>
    
    94
    +                <property name="expand">False</property>
    
    95
    +                <property name="fill">True</property>
    
    96
    +                <property name="position">2</property>
    
    97
    +              </packing>
    
    98
    +            </child>
    
    99
    +          </object>
    
    100
    +          <packing>
    
    101
    +            <property name="expand">False</property>
    
    102
    +            <property name="fill">True</property>
    
    103
    +            <property name="position">0</property>
    
    104
    +          </packing>
    
    105
    +        </child>
    
    106
    +        <child>
    
    107
    +          <placeholder/>
    
    108
    +        </child>
    
    109
    +        <style>
    
    110
    +          <class name="account-page-roster"/>
    
    111
    +        </style>
    
    112
    +      </object>
    
    113
    +      <packing>
    
    114
    +        <property name="resize">False</property>
    
    115
    +        <property name="shrink">False</property>
    
    116
    +      </packing>
    
    117
    +    </child>
    
    118
    +    <child>
    
    119
    +      <object class="GtkBox" id="account_box">
    
    120
    +        <property name="visible">True</property>
    
    121
    +        <property name="can-focus">False</property>
    
    122
    +        <property name="halign">center</property>
    
    123
    +        <property name="hexpand">True</property>
    
    124
    +        <property name="orientation">vertical</property>
    
    125
    +        <property name="spacing">6</property>
    
    126
    +        <child>
    
    127
    +          <object class="GtkBox">
    
    128
    +            <property name="visible">True</property>
    
    129
    +            <property name="can-focus">False</property>
    
    130
    +            <property name="spacing">12</property>
    
    131
    +            <child>
    
    132
    +              <object class="GtkLabel" id="account_label">
    
    133
    +                <property name="visible">True</property>
    
    134
    +                <property name="can-focus">False</property>
    
    135
    +                <style>
    
    136
    +                  <class name="large-header"/>
    
    137
    +                </style>
    
    138
    +              </object>
    
    139
    +              <packing>
    
    140
    +                <property name="expand">False</property>
    
    141
    +                <property name="fill">True</property>
    
    142
    +                <property name="position">0</property>
    
    143
    +              </packing>
    
    144
    +            </child>
    
    145
    +            <child>
    
    146
    +              <object class="GtkButton" id="account_settings">
    
    147
    +                <property name="visible">True</property>
    
    148
    +                <property name="can-focus">True</property>
    
    149
    +                <property name="receives-default">True</property>
    
    150
    +                <property name="tooltip-text" translatable="yes">Account Settings…</property>
    
    151
    +                <signal name="clicked" handler="_on_account_settings" swapped="no"/>
    
    152
    +                <child>
    
    153
    +                  <object class="GtkImage">
    
    154
    +                    <property name="visible">True</property>
    
    155
    +                    <property name="can-focus">False</property>
    
    156
    +                    <property name="icon-name">preferences-other-symbolic</property>
    
    157
    +                  </object>
    
    158
    +                </child>
    
    159
    +              </object>
    
    160
    +              <packing>
    
    161
    +                <property name="expand">False</property>
    
    162
    +                <property name="fill">True</property>
    
    163
    +                <property name="position">1</property>
    
    164
    +              </packing>
    
    165
    +            </child>
    
    166
    +          </object>
    
    167
    +          <packing>
    
    168
    +            <property name="expand">False</property>
    
    169
    +            <property name="fill">True</property>
    
    170
    +            <property name="position">0</property>
    
    171
    +          </packing>
    
    172
    +        </child>
    
    173
    +        <child>
    
    174
    +          <placeholder/>
    
    175
    +        </child>
    
    176
    +        <style>
    
    177
    +          <class name="account-page-box"/>
    
    178
    +        </style>
    
    179
    +      </object>
    
    180
    +      <packing>
    
    181
    +        <property name="resize">True</property>
    
    182
    +        <property name="shrink">True</property>
    
    183
    +      </packing>
    
    184
    +    </child>
    
    185
    +  </object>
    
    186
    +</interface>

  • gajim/data/gui/main.ui
    ... ... @@ -165,7 +165,7 @@
    165 165
                                 <property name="label">Workspace Label</property>
    
    166 166
                                 <property name="ellipsize">end</property>
    
    167 167
                                 <style>
    
    168
    -                              <class name="large-header"/>
    
    168
    +                              <class name="bold16"/>
    
    169 169
                                 </style>
    
    170 170
                               </object>
    
    171 171
                               <packing>
    

  • gajim/data/gui/roster.ui
    ... ... @@ -30,7 +30,6 @@
    30 30
         <child>
    
    31 31
           <object class="GtkTreeViewColumn" id="contact_column">
    
    32 32
             <property name="sizing">fixed</property>
    
    33
    -        <property name="fixed-width">210</property>
    
    34 33
             <property name="title">avatar</property>
    
    35 34
             <property name="expand">True</property>
    
    36 35
             <child>
    

  • gajim/data/style/gajim.css
    ... ... @@ -132,9 +132,20 @@
    132 132
         background-color: darker(@theme_bg_color);
    
    133 133
         margin: 0px 12px 0px 12px;
    
    134 134
     }
    
    135
    +
    
    135 136
     /* Account Page */
    
    136 137
     .account-page {
    
    137
    -    background: @theme_bg_color;
    
    138
    +    background: transparent;
    
    139
    +}
    
    140
    +.account-page-roster {
    
    141
    +	padding: 12px;
    
    142
    +}
    
    143
    +.account-page-box {
    
    144
    +    padding: 18px;
    
    145
    +}
    
    146
    +/* Roster */
    
    147
    +.roster treeview {
    
    148
    +	padding: 0 3px;
    
    138 149
     }
    
    139 150
     
    
    140 151
     /*Middle Grid*/
    
    ... ... @@ -416,9 +427,6 @@ infobar.error > revealer > box {
    416 427
     .start-chat-row:not(.activatable) label { color: @insensitive_fg_color; }
    
    417 428
     .start-chat-row:focus { outline: none; }
    
    418 429
     
    
    419
    -/* Roster */
    
    420
    -.roster treeview { padding-left: 4px; }
    
    421
    -
    
    422 430
     /* GroupChatRoster */
    
    423 431
     .groupchat-roster { border-left: 1px solid;
    
    424 432
                         border-color: @borders; }
    

  • gajim/gtk/account_page.py
    ... ... @@ -15,55 +15,41 @@
    15 15
     from gi.repository import Gtk
    
    16 16
     
    
    17 17
     from gajim.common import app
    
    18
    -from gajim.common.i18n import _
    
    19 18
     
    
    20 19
     from .roster import Roster
    
    21 20
     from .status_selector import StatusSelector
    
    21
    +from .util import get_builder
    
    22 22
     from .util import open_window
    
    23 23
     
    
    24 24
     
    
    25 25
     class AccountPage(Gtk.Box):
    
    26 26
         def __init__(self, account):
    
    27 27
             Gtk.Box.__init__(self)
    
    28
    -        self.get_style_context().add_class('account-page')
    
    29
    -
    
    30 28
             self._account = account
    
    31 29
     
    
    32
    -        self._account_label = Gtk.Label()
    
    33
    -        self._account_label.get_style_context().add_class('large-header')
    
    30
    +        self._ui = get_builder('account_page.ui')
    
    31
    +        self.add(self._ui.paned)
    
    34 32
     
    
    35 33
             self._status_selector = StatusSelector()
    
    36 34
             self._status_selector.set_halign(Gtk.Align.CENTER)
    
    37
    -
    
    38
    -        settings_button = Gtk.Button(label=_('Settings'))
    
    39
    -        settings_button.set_halign(Gtk.Align.CENTER)
    
    40
    -        settings_button.connect('clicked', self._on_settings)
    
    41
    -
    
    42
    -        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=18)
    
    43
    -        box.set_halign(Gtk.Align.CENTER)
    
    44
    -        box.set_valign(Gtk.Align.CENTER)
    
    45
    -        box.set_hexpand(True)
    
    46
    -        box.add(self._account_label)
    
    47
    -        box.add(settings_button)
    
    48
    -        box.add(self._status_selector)
    
    35
    +        self._ui.account_box.add(self._status_selector)
    
    49 36
     
    
    50 37
             self._roster = Roster(account)
    
    51
    -        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=12)
    
    52
    -        hbox.add(self._roster)
    
    53
    -        hbox.add(box)
    
    38
    +        self._ui.roster_box.add(self._roster)
    
    54 39
     
    
    55
    -        self.add(hbox)
    
    40
    +        self._ui.connect_signals(self)
    
    56 41
             self.show_all()
    
    42
    +
    
    57 43
             self.update()
    
    58 44
     
    
    59
    -    def _on_settings(self, _button):
    
    45
    +    def _on_account_settings(self, _button):
    
    60 46
             window = open_window('AccountsWindow')
    
    61 47
             window.select_account(self._account)
    
    62 48
     
    
    63 49
         def update(self):
    
    64 50
             account_label = app.settings.get_account_setting(
    
    65 51
                 self._account, 'account_label')
    
    66
    -        self._account_label.set_text(account_label)
    
    52
    +        self._ui.account_label.set_text(account_label)
    
    67 53
             self._status_selector.update()
    
    68 54
     
    
    69 55
         def process_event(self, event):
    

  • gajim/gtk/chat_list.py
    1 1
     import logging
    
    2 2
     
    
    3
    +from gi.repository import Gdk
    
    3 4
     from gi.repository import GLib
    
    4 5
     from gi.repository import Gtk
    
    5 6
     
    
    ... ... @@ -14,7 +15,6 @@
    14 15
     
    
    15 16
     from gajim.gui_menu_builder import get_chat_list_row_menu
    
    16 17
     
    
    17
    -from .tooltips import RosterTooltip
    
    18 18
     from .util import get_builder
    
    19 19
     
    
    20 20
     log = logging.getLogger('gajim.gui.chatlist')
    
    ... ... @@ -32,7 +32,6 @@ def __init__(self, workspace_id):
    32 32
             self.set_filter_func(self._filter_func)
    
    33 33
             self.set_header_func(self._header_func)
    
    34 34
             self.set_sort_func(self._sort_func)
    
    35
    -        self.set_has_tooltip(True)
    
    36 35
             self._set_placeholder()
    
    37 36
     
    
    38 37
             self.connect('destroy', self._on_destroy)
    
    ... ... @@ -340,13 +339,21 @@ def is_pinned(self):
    340 339
     
    
    341 340
         def _on_button_press(self, _widget, event):
    
    342 341
             if event.button == 3:  # right click
    
    343
    -            self._popup_menu()
    
    342
    +            self._popup_menu(event)
    
    344 343
     
    
    345
    -    def _popup_menu(self):
    
    344
    +    def _popup_menu(self, event):
    
    346 345
             menu = get_chat_list_row_menu(
    
    347 346
                 self.workspace_id, self.account, self.jid, self._pinned)
    
    347
    +
    
    348
    +        rectangle = Gdk.Rectangle()
    
    349
    +        rectangle.x = event.x
    
    350
    +        rectangle.y = event.y
    
    351
    +        rectangle.width = rectangle.height = 1
    
    352
    +
    
    348 353
             popover = Gtk.Popover.new_from_model(self, menu)
    
    349
    -        popover.set_position(Gtk.PositionType.BOTTOM)
    
    354
    +        popover.set_relative_to(self)
    
    355
    +        popover.set_position(Gtk.PositionType.RIGHT)
    
    356
    +        popover.set_pointing_to(rectangle)
    
    350 357
             popover.popup()
    
    351 358
     
    
    352 359
         def toggle_pinned(self):
    

  • gajim/gtk/roster.py
    ... ... @@ -3,6 +3,7 @@
    3 3
     from typing import Optional
    
    4 4
     from enum import IntEnum
    
    5 5
     
    
    6
    +from gi.repository import Gdk
    
    6 7
     from gi.repository import GLib
    
    7 8
     from gi.repository import Gtk
    
    8 9
     from gi.repository import GObject
    
    ... ... @@ -13,6 +14,8 @@
    13 14
     from gajim.common.const import StyleAttr
    
    14 15
     from gajim.common.i18n import _
    
    15 16
     
    
    17
    +from gajim.gui_menu_builder import get_roster_menu
    
    18
    +
    
    16 19
     from .util import EventHelper
    
    17 20
     from .util import get_builder
    
    18 21
     
    
    ... ... @@ -43,7 +46,8 @@ class Roster(Gtk.ScrolledWindow, EventHelper):
    43 46
         def __init__(self, account):
    
    44 47
             Gtk.ScrolledWindow.__init__(self)
    
    45 48
             EventHelper.__init__(self)
    
    46
    -        self.set_size_request(300, -1)
    
    49
    +        self.set_size_request(200, -1)
    
    50
    +        self.set_vexpand(True)
    
    47 51
             self.get_style_context().add_class('roster')
    
    48 52
     
    
    49 53
             self._account = account
    
    ... ... @@ -80,8 +84,8 @@ def _on_roster_row_activated(self, _treeview, path, _column):
    80 84
                 # This is a group row
    
    81 85
                 return
    
    82 86
     
    
    83
    -        nick = self._store[iter_][Column.JID_OR_GROUP]
    
    84
    -        self.emit('row-activated', nick)
    
    87
    +        jid = self._store[iter_][Column.JID_OR_GROUP]
    
    88
    +        self.emit('row-activated', jid)
    
    85 89
     
    
    86 90
         def _on_roster_button_press_event(self, treeview, event):
    
    87 91
             if event.button not in (2, 3):
    
    ... ... @@ -97,13 +101,13 @@ def _on_roster_button_press_event(self, treeview, event):
    97 101
                 # Group row
    
    98 102
                 return
    
    99 103
     
    
    100
    -        nick = self._store[iter_][Column.JID_OR_GROUP]
    
    104
    +        jid = self._store[iter_][Column.JID_OR_GROUP]
    
    101 105
     
    
    102 106
             if event.button == 3:  # right click
    
    103
    -            self._show_contact_menu(nick)
    
    107
    +            self._show_contact_menu(jid, treeview, event)
    
    104 108
     
    
    105 109
             if event.button == 2:  # middle click
    
    106
    -            self.emit('row-activated', nick)
    
    110
    +            self.emit('row-activated', jid)
    
    107 111
     
    
    108 112
         @staticmethod
    
    109 113
         def _on_focus_out(treeview, _param):
    
    ... ... @@ -112,15 +116,26 @@ def _on_focus_out(treeview, _param):
    112 116
         def _on_theme_update(self, _event):
    
    113 117
             self.redraw()
    
    114 118
     
    
    115
    -    def _show_contact_menu(self, nick):
    
    116
    -        pass
    
    119
    +    def _show_contact_menu(self, jid, treeview, event):
    
    120
    +        menu = get_roster_menu(self._account, jid)
    
    121
    +
    
    122
    +        rectangle = Gdk.Rectangle()
    
    123
    +        rectangle.x = event.x
    
    124
    +        rectangle.y = event.y
    
    125
    +        rectangle.width = rectangle.height = 1
    
    126
    +
    
    127
    +        popover = Gtk.Popover.new_from_model(self, menu)
    
    128
    +        popover.set_relative_to(treeview)
    
    129
    +        popover.set_position(Gtk.PositionType.RIGHT)
    
    130
    +        popover.set_pointing_to(rectangle)
    
    131
    +        popover.popup()
    
    117 132
     
    
    118 133
         def _on_destroy(self, _roster):
    
    119 134
             self._contact_refs = {}
    
    120 135
             self._group_refs = {}
    
    121 136
             self._roster.set_model(None)
    
    122 137
             self._roster = None
    
    123
    -        # Store keeps a ref on the object if we dont unset the sort func
    
    138
    +        # Store keeps a ref on the object if we don’t unset the sort func
    
    124 139
             self._store.set_sort_func(Column.TEXT, print)
    
    125 140
             self._store.clear()
    
    126 141
             self._store = None
    
    ... ... @@ -188,13 +203,15 @@ def _add_contact(self, contact):
    188 203
             # Avatar
    
    189 204
             surface = contact.get_avatar(AvatarSize.CHAT, self.get_scale_factor())
    
    190 205
     
    
    206
    +        jid = str(contact.jid)
    
    207
    +        # TODO: Multiple groups per contact ?
    
    191 208
             iter_ = self._store.append(
    
    192
    -            group_iter, (surface, contact.name, True, str(contact.jid)))
    
    193
    -        self._contact_refs[contact.jid] = Gtk.TreeRowReference(
    
    209
    +            group_iter, (surface, contact.name, True, jid))
    
    210
    +        self._contact_refs[jid] = Gtk.TreeRowReference(
    
    194 211
                 self._store, self._store.get_path(iter_))
    
    195 212
     
    
    196 213
             self.draw_groups()
    
    197
    -        self.draw_contact(contact.jid)
    
    214
    +        self.draw_contact(jid)
    
    198 215
     
    
    199 216
             if (group_path is not None and
    
    200 217
                     self._roster.get_model() is not None):
    
    ... ... @@ -224,14 +241,13 @@ def draw_contact(self, jid):
    224 241
             if not iter_:
    
    225 242
                 return
    
    226 243
     
    
    227
    -        client = app.get_client(self._account)
    
    228
    -        contact = client.get_module('Contacts').get_contact(jid)
    
    244
    +        contact = self._client.get_module('Contacts').get_contact(jid)
    
    229 245
     
    
    230 246
             self.draw_avatar(contact)
    
    231 247
             self._store[iter_][Column.TEXT] = GLib.markup_escape_text(contact.name)
    
    232 248
     
    
    233 249
         def draw_avatar(self, contact):
    
    234
    -        iter_ = self._get_contact_iter(contact.jid)
    
    250
    +        iter_ = self._get_contact_iter(str(contact.jid))
    
    235 251
             if iter_ is None:
    
    236 252
                 return
    
    237 253
     
    

  • gajim/gui_menu_builder.py
    ... ... @@ -796,8 +796,25 @@ def get_conv_context_menu(account, uri):
    796 796
         return menu
    
    797 797
     
    
    798 798
     
    
    799
    +def get_roster_menu(account, jid):
    
    800
    +    menu_items = [
    
    801
    +        ('show-contact-info', _('Contact Info')),
    
    802
    +    ]
    
    803
    +    menu = Gio.Menu()
    
    804
    +    for item in menu_items:
    
    805
    +        action, label = item
    
    806
    +        action = f'win.{action}'
    
    807
    +        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)
    
    811
    +        menu.append_item(menuitem)
    
    812
    +
    
    813
    +    return menu
    
    814
    +
    
    815
    +
    
    799 816
     def get_chat_list_row_menu(workspace_id, account, jid, pinned):
    
    800
    -    toggle_label = _('Unpin Conversation') if pinned else _('Pin Conversation')
    
    817
    +    toggle_label = _('Unpin Chat') if pinned else _('Pin Chat')
    
    801 818
         menu_items = [
    
    802 819
             ('toggle-chat-pinned', toggle_label),
    
    803 820
             (_('Move Chat'), []),