Philipp Hörist pushed to branch master at gajim / gajim

Commits:

4 changed files:

Changes:

  • gajim/data/gui/start_chat_dialog.ui
    ... ... @@ -2,84 +2,20 @@
    2 2
     <!-- Generated with glade 3.22.1 -->
    
    3 3
     <interface>
    
    4 4
       <requires lib="gtk+" version="3.20"/>
    
    5
    -  <object class="GtkGrid" id="search_result_grid">
    
    6
    -    <property name="visible">True</property>
    
    7
    -    <property name="can_focus">False</property>
    
    8
    -    <child>
    
    9
    -      <object class="GtkLabel" id="name_label">
    
    10
    -        <property name="visible">True</property>
    
    11
    -        <property name="can_focus">False</property>
    
    12
    -        <property name="halign">start</property>
    
    13
    -        <property name="ellipsize">end</property>
    
    14
    -        <property name="max_width_chars">50</property>
    
    15
    -        <property name="xalign">0</property>
    
    16
    -        <style>
    
    17
    -          <class name="bold"/>
    
    18
    -        </style>
    
    19
    -      </object>
    
    20
    -      <packing>
    
    21
    -        <property name="left_attach">0</property>
    
    22
    -        <property name="top_attach">0</property>
    
    23
    -      </packing>
    
    24
    -    </child>
    
    25
    -    <child>
    
    26
    -      <object class="GtkLabel" id="jid_label">
    
    27
    -        <property name="visible">True</property>
    
    28
    -        <property name="can_focus">False</property>
    
    29
    -        <property name="halign">start</property>
    
    30
    -        <property name="hexpand">True</property>
    
    31
    -        <property name="ellipsize">end</property>
    
    32
    -        <property name="max_width_chars">50</property>
    
    33
    -        <property name="xalign">0</property>
    
    34
    -      </object>
    
    35
    -      <packing>
    
    36
    -        <property name="left_attach">0</property>
    
    37
    -        <property name="top_attach">1</property>
    
    38
    -        <property name="width">2</property>
    
    39
    -      </packing>
    
    40
    -    </child>
    
    41
    -    <child>
    
    42
    -      <object class="GtkBox">
    
    43
    -        <property name="visible">True</property>
    
    44
    -        <property name="can_focus">False</property>
    
    45
    -        <property name="spacing">6</property>
    
    46
    -        <child>
    
    47
    -          <object class="GtkImage">
    
    48
    -            <property name="visible">True</property>
    
    49
    -            <property name="can_focus">False</property>
    
    50
    -            <property name="icon_name">system-users-symbolic</property>
    
    51
    -          </object>
    
    52
    -          <packing>
    
    53
    -            <property name="expand">False</property>
    
    54
    -            <property name="fill">True</property>
    
    55
    -            <property name="pack_type">end</property>
    
    56
    -            <property name="position">0</property>
    
    57
    -          </packing>
    
    58
    -        </child>
    
    59
    -        <child>
    
    60
    -          <object class="GtkLabel" id="user_label">
    
    61
    -            <property name="visible">True</property>
    
    62
    -            <property name="can_focus">False</property>
    
    63
    -            <property name="tooltip_text" translatable="yes">Users</property>
    
    64
    -            <property name="xalign">1</property>
    
    65
    -          </object>
    
    66
    -          <packing>
    
    67
    -            <property name="expand">False</property>
    
    68
    -            <property name="fill">True</property>
    
    69
    -            <property name="pack_type">end</property>
    
    70
    -            <property name="position">1</property>
    
    71
    -          </packing>
    
    72
    -        </child>
    
    73
    -      </object>
    
    74
    -      <packing>
    
    75
    -        <property name="left_attach">1</property>
    
    76
    -        <property name="top_attach">0</property>
    
    77
    -      </packing>
    
    78
    -    </child>
    
    5
    +  <object class="GtkListStore" id="account_store">
    
    6
    +    <columns>
    
    7
    +      <!-- column-name icon -->
    
    8
    +      <column type="GdkPixbuf"/>
    
    9
    +      <!-- column-name account -->
    
    10
    +      <column type="gchararray"/>
    
    11
    +      <!-- column-name account_label -->
    
    12
    +      <column type="gchararray"/>
    
    13
    +    </columns>
    
    79 14
       </object>
    
    80 15
       <object class="GtkStack" id="stack">
    
    81 16
         <property name="visible">True</property>
    
    82 17
         <property name="can_focus">False</property>
    
    18
    +    <signal name="notify::visible-child-name" handler="_on_page_changed" swapped="no"/>
    
    83 19
         <child>
    
    84 20
           <object class="GtkBox" id="box">
    
    85 21
             <property name="visible">True</property>
    
    ... ... @@ -88,14 +24,50 @@
    88 24
             <property name="orientation">vertical</property>
    
    89 25
             <property name="spacing">6</property>
    
    90 26
             <child>
    
    91
    -          <object class="GtkSearchEntry" id="search_entry">
    
    27
    +          <object class="GtkBox">
    
    92 28
                 <property name="visible">True</property>
    
    93
    -            <property name="can_focus">True</property>
    
    94
    -            <property name="has_focus">True</property>
    
    95
    -            <property name="is_focus">True</property>
    
    96
    -            <property name="primary_icon_name">edit-find-symbolic</property>
    
    97
    -            <property name="primary_icon_activatable">False</property>
    
    98
    -            <property name="primary_icon_sensitive">False</property>
    
    29
    +            <property name="can_focus">False</property>
    
    30
    +            <property name="spacing">6</property>
    
    31
    +            <child>
    
    32
    +              <object class="GtkSearchEntry" id="search_entry">
    
    33
    +                <property name="visible">True</property>
    
    34
    +                <property name="can_focus">True</property>
    
    35
    +                <property name="has_focus">True</property>
    
    36
    +                <property name="is_focus">True</property>
    
    37
    +                <property name="hexpand">True</property>
    
    38
    +                <property name="primary_icon_name">edit-find-symbolic</property>
    
    39
    +                <property name="primary_icon_activatable">False</property>
    
    40
    +                <property name="primary_icon_sensitive">False</property>
    
    41
    +              </object>
    
    42
    +              <packing>
    
    43
    +                <property name="expand">False</property>
    
    44
    +                <property name="fill">True</property>
    
    45
    +                <property name="position">0</property>
    
    46
    +              </packing>
    
    47
    +            </child>
    
    48
    +            <child>
    
    49
    +              <object class="GtkToggleButton" id="global_search_toggle">
    
    50
    +                <property name="visible">True</property>
    
    51
    +                <property name="can_focus">True</property>
    
    52
    +                <property name="receives_default">True</property>
    
    53
    +                <property name="tooltip_text" translatable="yes">Global Group Chat Search</property>
    
    54
    +                <property name="halign">end</property>
    
    55
    +                <property name="relief">half</property>
    
    56
    +                <signal name="toggled" handler="_on_global_search_toggle" swapped="no"/>
    
    57
    +                <child>
    
    58
    +                  <object class="GtkImage">
    
    59
    +                    <property name="visible">True</property>
    
    60
    +                    <property name="can_focus">False</property>
    
    61
    +                    <property name="icon_name">content-loading-symbolic</property>
    
    62
    +                  </object>
    
    63
    +                </child>
    
    64
    +              </object>
    
    65
    +              <packing>
    
    66
    +                <property name="expand">False</property>
    
    67
    +                <property name="fill">True</property>
    
    68
    +                <property name="position">1</property>
    
    69
    +              </packing>
    
    70
    +            </child>
    
    99 71
               </object>
    
    100 72
               <packing>
    
    101 73
                 <property name="expand">False</property>
    
    ... ... @@ -304,143 +276,140 @@
    304 276
             <property name="position">3</property>
    
    305 277
           </packing>
    
    306 278
         </child>
    
    307
    -  </object>
    
    308
    -  <object class="GtkGrid" id="tooltip">
    
    309
    -    <property name="visible">True</property>
    
    310
    -    <property name="can_focus">False</property>
    
    311
    -    <property name="column_spacing">6</property>
    
    312 279
         <child>
    
    313
    -      <object class="GtkLabel" id="tooltip_name">
    
    280
    +      <object class="GtkBox">
    
    281
    +        <property name="visible">True</property>
    
    314 282
             <property name="can_focus">False</property>
    
    315
    -        <property name="no_show_all">True</property>
    
    316
    -        <property name="halign">start</property>
    
    317
    -        <property name="ellipsize">end</property>
    
    318
    -        <property name="max_width_chars">50</property>
    
    319
    -        <property name="xalign">0</property>
    
    283
    +        <property name="orientation">vertical</property>
    
    284
    +        <property name="spacing">6</property>
    
    285
    +        <child>
    
    286
    +          <object class="GtkLabel">
    
    287
    +            <property name="visible">True</property>
    
    288
    +            <property name="can_focus">False</property>
    
    289
    +            <property name="label" translatable="yes">Select Account</property>
    
    290
    +            <property name="justify">center</property>
    
    291
    +            <property name="wrap">True</property>
    
    292
    +            <style>
    
    293
    +              <class name="bold16"/>
    
    294
    +              <class name="margin-12"/>
    
    295
    +            </style>
    
    296
    +          </object>
    
    297
    +          <packing>
    
    298
    +            <property name="expand">False</property>
    
    299
    +            <property name="fill">True</property>
    
    300
    +            <property name="position">0</property>
    
    301
    +          </packing>
    
    302
    +        </child>
    
    303
    +        <child>
    
    304
    +          <object class="GtkScrolledWindow">
    
    305
    +            <property name="visible">True</property>
    
    306
    +            <property name="can_focus">True</property>
    
    307
    +            <property name="vexpand">True</property>
    
    308
    +            <property name="hscrollbar_policy">never</property>
    
    309
    +            <property name="shadow_type">in</property>
    
    310
    +            <child>
    
    311
    +              <object class="GtkTreeView" id="account_view">
    
    312
    +                <property name="visible">True</property>
    
    313
    +                <property name="can_focus">True</property>
    
    314
    +                <property name="model">account_store</property>
    
    315
    +                <property name="headers_visible">False</property>
    
    316
    +                <property name="enable_search">False</property>
    
    317
    +                <property name="show_expanders">False</property>
    
    318
    +                <child internal-child="selection">
    
    319
    +                  <object class="GtkTreeSelection"/>
    
    320
    +                </child>
    
    321
    +                <child>
    
    322
    +                  <object class="GtkTreeViewColumn">
    
    323
    +                    <property name="title" translatable="yes">icon</property>
    
    324
    +                    <child>
    
    325
    +                      <object class="GtkCellRendererPixbuf" id="icon_pixbuf"/>
    
    326
    +                      <attributes>
    
    327
    +                        <attribute name="pixbuf">0</attribute>
    
    328
    +                      </attributes>
    
    329
    +                    </child>
    
    330
    +                  </object>
    
    331
    +                </child>
    
    332
    +                <child>
    
    333
    +                  <object class="GtkTreeViewColumn">
    
    334
    +                    <property name="title" translatable="yes">account</property>
    
    335
    +                    <child>
    
    336
    +                      <object class="GtkCellRendererText" id="account_text"/>
    
    337
    +                      <attributes>
    
    338
    +                        <attribute name="text">2</attribute>
    
    339
    +                      </attributes>
    
    340
    +                    </child>
    
    341
    +                  </object>
    
    342
    +                </child>
    
    343
    +                <style>
    
    344
    +                  <class name="start-chat-treeview"/>
    
    345
    +                </style>
    
    346
    +              </object>
    
    347
    +            </child>
    
    348
    +            <style>
    
    349
    +              <class name="start-chat-scrolled"/>
    
    350
    +            </style>
    
    351
    +          </object>
    
    352
    +          <packing>
    
    353
    +            <property name="expand">False</property>
    
    354
    +            <property name="fill">True</property>
    
    355
    +            <property name="position">1</property>
    
    356
    +          </packing>
    
    357
    +        </child>
    
    358
    +        <child>
    
    359
    +          <object class="GtkBox">
    
    360
    +            <property name="visible">True</property>
    
    361
    +            <property name="can_focus">False</property>
    
    362
    +            <property name="homogeneous">True</property>
    
    363
    +            <child>
    
    364
    +              <object class="GtkButton">
    
    365
    +                <property name="label" translatable="yes">_Back</property>
    
    366
    +                <property name="visible">True</property>
    
    367
    +                <property name="can_focus">True</property>
    
    368
    +                <property name="receives_default">True</property>
    
    369
    +                <property name="halign">start</property>
    
    370
    +                <property name="use_underline">True</property>
    
    371
    +                <signal name="clicked" handler="_on_back_clicked" swapped="no"/>
    
    372
    +              </object>
    
    373
    +              <packing>
    
    374
    +                <property name="expand">False</property>
    
    375
    +                <property name="fill">True</property>
    
    376
    +                <property name="position">0</property>
    
    377
    +              </packing>
    
    378
    +            </child>
    
    379
    +            <child>
    
    380
    +              <object class="GtkButton">
    
    381
    +                <property name="label" translatable="yes">_Select</property>
    
    382
    +                <property name="visible">True</property>
    
    383
    +                <property name="can_focus">True</property>
    
    384
    +                <property name="receives_default">True</property>
    
    385
    +                <property name="halign">end</property>
    
    386
    +                <property name="use_underline">True</property>
    
    387
    +                <signal name="clicked" handler="_on_select_clicked" swapped="no"/>
    
    388
    +                <style>
    
    389
    +                  <class name="suggested-action"/>
    
    390
    +                </style>
    
    391
    +              </object>
    
    392
    +              <packing>
    
    393
    +                <property name="expand">False</property>
    
    394
    +                <property name="fill">True</property>
    
    395
    +                <property name="position">1</property>
    
    396
    +              </packing>
    
    397
    +            </child>
    
    398
    +          </object>
    
    399
    +          <packing>
    
    400
    +            <property name="expand">False</property>
    
    401
    +            <property name="fill">True</property>
    
    402
    +            <property name="pack_type">end</property>
    
    403
    +            <property name="position">2</property>
    
    404
    +          </packing>
    
    405
    +        </child>
    
    320 406
             <style>
    
    321
    -          <class name="bold"/>
    
    407
    +          <class name="margin-18"/>
    
    322 408
             </style>
    
    323 409
           </object>
    
    324 410
           <packing>
    
    325
    -        <property name="left_attach">1</property>
    
    326
    -        <property name="top_attach">0</property>
    
    327
    -      </packing>
    
    328
    -    </child>
    
    329
    -    <child>
    
    330
    -      <object class="GtkLabel" id="tooltip_jid">
    
    331
    -        <property name="visible">True</property>
    
    332
    -        <property name="can_focus">False</property>
    
    333
    -        <property name="halign">start</property>
    
    334
    -        <property name="hexpand">True</property>
    
    335
    -        <property name="ellipsize">end</property>
    
    336
    -        <property name="max_width_chars">50</property>
    
    337
    -        <property name="xalign">0</property>
    
    338
    -      </object>
    
    339
    -      <packing>
    
    340
    -        <property name="left_attach">1</property>
    
    341
    -        <property name="top_attach">2</property>
    
    342
    -      </packing>
    
    343
    -    </child>
    
    344
    -    <child>
    
    345
    -      <object class="GtkLabel" id="tooltip_description">
    
    346
    -        <property name="can_focus">False</property>
    
    347
    -        <property name="no_show_all">True</property>
    
    348
    -        <property name="halign">start</property>
    
    349
    -        <property name="wrap">True</property>
    
    350
    -        <property name="max_width_chars">65</property>
    
    351
    -        <property name="xalign">0</property>
    
    352
    -      </object>
    
    353
    -      <packing>
    
    354
    -        <property name="left_attach">1</property>
    
    355
    -        <property name="top_attach">1</property>
    
    356
    -      </packing>
    
    357
    -    </child>
    
    358
    -    <child>
    
    359
    -      <object class="GtkLabel" id="tooltip_name_label">
    
    360
    -        <property name="visible">True</property>
    
    361
    -        <property name="can_focus">False</property>
    
    362
    -        <property name="label" translatable="yes">Name:</property>
    
    363
    -        <property name="xalign">1</property>
    
    364
    -      </object>
    
    365
    -      <packing>
    
    366
    -        <property name="left_attach">0</property>
    
    367
    -        <property name="top_attach">0</property>
    
    368
    -      </packing>
    
    369
    -    </child>
    
    370
    -    <child>
    
    371
    -      <object class="GtkLabel" id="tooltip_description_label">
    
    372
    -        <property name="visible">True</property>
    
    373
    -        <property name="can_focus">False</property>
    
    374
    -        <property name="label" translatable="yes">Description:</property>
    
    375
    -        <property name="xalign">1</property>
    
    376
    -      </object>
    
    377
    -      <packing>
    
    378
    -        <property name="left_attach">0</property>
    
    379
    -        <property name="top_attach">1</property>
    
    380
    -      </packing>
    
    381
    -    </child>
    
    382
    -    <child>
    
    383
    -      <object class="GtkLabel">
    
    384
    -        <property name="visible">True</property>
    
    385
    -        <property name="can_focus">False</property>
    
    386
    -        <property name="label" translatable="yes">Address:</property>
    
    387
    -        <property name="xalign">1</property>
    
    388
    -      </object>
    
    389
    -      <packing>
    
    390
    -        <property name="left_attach">0</property>
    
    391
    -        <property name="top_attach">2</property>
    
    392
    -      </packing>
    
    393
    -    </child>
    
    394
    -    <child>
    
    395
    -      <object class="GtkLabel" id="tooltip_user">
    
    396
    -        <property name="visible">True</property>
    
    397
    -        <property name="can_focus">False</property>
    
    398
    -        <property name="halign">start</property>
    
    399
    -        <property name="xalign">0</property>
    
    400
    -      </object>
    
    401
    -      <packing>
    
    402
    -        <property name="left_attach">1</property>
    
    403
    -        <property name="top_attach">4</property>
    
    404
    -      </packing>
    
    405
    -    </child>
    
    406
    -    <child>
    
    407
    -      <object class="GtkImage">
    
    408
    -        <property name="visible">True</property>
    
    409
    -        <property name="can_focus">False</property>
    
    410
    -        <property name="halign">end</property>
    
    411
    -        <property name="valign">center</property>
    
    412
    -        <property name="icon_name">system-users-symbolic</property>
    
    413
    -      </object>
    
    414
    -      <packing>
    
    415
    -        <property name="left_attach">0</property>
    
    416
    -        <property name="top_attach">4</property>
    
    417
    -      </packing>
    
    418
    -    </child>
    
    419
    -    <child>
    
    420
    -      <object class="GtkLabel" id="anonymous_label">
    
    421
    -        <property name="visible">True</property>
    
    422
    -        <property name="can_focus">False</property>
    
    423
    -        <property name="label" translatable="yes">Semi-Anonymous
    
    424
    -&lt;span size="small"&gt;(Only moderators can see your XMPP-Address)&lt;/span&gt;</property>
    
    425
    -        <property name="use_markup">True</property>
    
    426
    -        <property name="xalign">0</property>
    
    427
    -      </object>
    
    428
    -      <packing>
    
    429
    -        <property name="left_attach">1</property>
    
    430
    -        <property name="top_attach">3</property>
    
    431
    -      </packing>
    
    432
    -    </child>
    
    433
    -    <child>
    
    434
    -      <object class="GtkImage" id="anonymous_icon">
    
    435
    -        <property name="visible">True</property>
    
    436
    -        <property name="can_focus">False</property>
    
    437
    -        <property name="halign">end</property>
    
    438
    -        <property name="valign">center</property>
    
    439
    -        <property name="icon_name">security-medium-symbolic</property>
    
    440
    -      </object>
    
    441
    -      <packing>
    
    442
    -        <property name="left_attach">0</property>
    
    443
    -        <property name="top_attach">3</property>
    
    411
    +        <property name="name">account</property>
    
    412
    +        <property name="position">4</property>
    
    444 413
           </packing>
    
    445 414
         </child>
    
    446 415
       </object>
    

  • gajim/data/style/gajim.css
    ... ... @@ -135,12 +135,10 @@ list.settings > row > box {
    135 135
         font-weight: bold;
    
    136 136
         color: @insensitive_fg_color;}
    
    137 137
     
    
    138
    -/* StartChatListBox */
    
    139
    -#StartChatListBox > row { border-bottom: 1px solid; border-color: @theme_unfocused_bg_color; }
    
    140
    -#StartChatListBox > row:last-child { border-bottom: 0px}
    
    141
    -#StartChatListBox > row.activatable:active { box-shadow: none; }
    
    142
    -#StartChatListBox > row { padding: 10px 20px 10px 10px; }
    
    143
    -#StartChatListBox > row:not(.activatable) label { color: @insensitive_fg_color }
    
    138
    +/* Start Chat Accounts Treeview */
    
    139
    +.start-chat-treeview { padding: 5px; }
    
    140
    +.start-chat-treeview:focus {outline: none; }
    
    141
    +.start-chat-scrolled { border: 1px solid; border-color:@unfocused_borders; }
    
    144 142
     
    
    145 143
     /* StartChatListBox */
    
    146 144
     .start-chat-row { border-bottom: 1px solid; border-color: @theme_unfocused_bg_color; }
    
    ... ... @@ -258,7 +256,6 @@ button.flat.link { padding: 0; border: 0; }
    258 256
     /*Image Preview*/
    
    259 257
     .preview-image { box-shadow: 0px 0px 3px 0px alpha(@theme_text_color, 0.2); }
    
    260 258
     
    
    261
    -
    
    262 259
     /* Treeview */
    
    263 260
     .adhoc-treeview { padding: 5px; }
    
    264 261
     .adhoc-scrolled { border: 1px solid; border-color:@unfocused_borders; }
    

  • gajim/gtk/groupchat_info.py
    ... ... @@ -101,14 +101,21 @@ class GroupChatInfoScrolled(Gtk.ScrolledWindow):
    101 101
             self.set_policy(Gtk.PolicyType.NEVER,
    
    102 102
                             Gtk.PolicyType.AUTOMATIC)
    
    103 103
             self._account = account
    
    104
    +        self._info = None
    
    104 105
             self._ui = get_builder('groupchat_info_scrolled.ui')
    
    105 106
             self.add(self._ui.info_grid)
    
    106 107
             self._ui.connect_signals(self)
    
    107 108
             self.show_all()
    
    108 109
     
    
    110
    +    def get_account(self):
    
    111
    +        return self._account
    
    112
    +
    
    109 113
         def set_account(self, account):
    
    110 114
             self._account = account
    
    111 115
     
    
    116
    +    def get_jid(self):
    
    117
    +        return self._info.jid
    
    118
    +
    
    112 119
         def set_author(self, author, epoch_timestamp=None):
    
    113 120
             if not author:
    
    114 121
                 return
    
    ... ... @@ -129,6 +136,7 @@ class GroupChatInfoScrolled(Gtk.ScrolledWindow):
    129 136
             self._ui.subject_label.set_visible(True)
    
    130 137
     
    
    131 138
         def set_from_disco_info(self, info):
    
    139
    +        self._info = info
    
    132 140
             # Set name
    
    133 141
             has_name = bool(info.muc_name)
    
    134 142
             self._ui.name.set_text(info.muc_name or '')
    

  • gajim/gtk/start_chat.py
    ... ... @@ -23,7 +23,6 @@ from gi.repository import Pango
    23 23
     from nbxmpp.protocol import InvalidJid
    
    24 24
     from nbxmpp.protocol import JID
    
    25 25
     from nbxmpp.util import is_error_result
    
    26
    -from nbxmpp.const import AnonymityMode
    
    27 26
     
    
    28 27
     from gajim.common import app
    
    29 28
     from gajim.common import helpers
    
    ... ... @@ -39,7 +38,7 @@ from gajim.gtk.util import ensure_not_destroyed
    39 38
     
    
    40 39
     class Search(IntEnum):
    
    41 40
         CONTACT = 0
    
    42
    -    MUC = 1
    
    41
    +    GLOBAL = 1
    
    43 42
     
    
    44 43
     
    
    45 44
     class StartChatDialog(Gtk.ApplicationWindow):
    
    ... ... @@ -62,9 +61,10 @@ class StartChatDialog(Gtk.ApplicationWindow):
    62 61
             self.new_contact_row_visible = False
    
    63 62
             self.new_contact_rows = {}
    
    64 63
             self.new_groupchat_rows = {}
    
    65
    -        self.accounts = app.connections.keys()
    
    66
    -        self.add_contacts()
    
    67
    -        self.add_groupchats()
    
    64
    +        self._accounts = app.get_enabled_accounts_with_labels()
    
    65
    +        self._add_accounts()
    
    66
    +        self._add_contacts()
    
    67
    +        self._add_groupchats()
    
    68 68
     
    
    69 69
             self._ui.search_entry.connect('search-changed',
    
    70 70
                                           self._on_search_changed)
    
    ... ... @@ -79,7 +79,9 @@ class StartChatDialog(Gtk.ApplicationWindow):
    79 79
             self._ui.listbox.set_sort_func(self._sort_func, None)
    
    80 80
             self._ui.listbox.connect('row-activated', self._on_row_activated)
    
    81 81
     
    
    82
    -        self._muc_search_listbox = MUCSearch()
    
    82
    +        self._global_search_listbox = GlobalSearch()
    
    83
    +        self._global_search_listbox.connect('row-activated',
    
    84
    +                                            self._on_row_activated)
    
    83 85
             self._current_listbox = self._ui.listbox
    
    84 86
     
    
    85 87
             self._muc_info_box = GroupChatInfoScrolled()
    
    ... ... @@ -95,9 +97,16 @@ class StartChatDialog(Gtk.ApplicationWindow):
    95 97
         def set_search_text(self, text):
    
    96 98
             self._ui.search_entry.set_text(text)
    
    97 99
     
    
    98
    -    def add_contacts(self):
    
    99
    -        show_account = len(self.accounts) > 1
    
    100
    -        for account in self.accounts:
    
    100
    +    def _global_search_active(self):
    
    101
    +        return self._ui.global_search_toggle.get_active()
    
    102
    +
    
    103
    +    def _add_accounts(self):
    
    104
    +        for account in self._accounts:
    
    105
    +            self._ui.account_store.append([None, *account])
    
    106
    +
    
    107
    +    def _add_contacts(self):
    
    108
    +        show_account = len(self._accounts) > 1
    
    109
    +        for account, _label in self._accounts:
    
    101 110
                 self.new_contact_rows[account] = None
    
    102 111
                 for jid in app.contacts.get_jid_list(account):
    
    103 112
                     contact = app.contacts.get_contact_with_highest_priority(
    
    ... ... @@ -108,9 +117,9 @@ class StartChatDialog(Gtk.ApplicationWindow):
    108 117
                                      contact.get_shown_name(), show_account)
    
    109 118
                     self._ui.listbox.add(row)
    
    110 119
     
    
    111
    -    def add_groupchats(self):
    
    112
    -        show_account = len(self.accounts) > 1
    
    113
    -        for account in self.accounts:
    
    120
    +    def _add_groupchats(self):
    
    121
    +        show_account = len(self._accounts) > 1
    
    122
    +        for account, _label in self._accounts:
    
    114 123
                 self.new_groupchat_rows[account] = None
    
    115 124
                 con = app.connections[account]
    
    116 125
                 bookmarks = con.get_module('Bookmarks').bookmarks
    
    ... ... @@ -131,42 +140,72 @@ class StartChatDialog(Gtk.ApplicationWindow):
    131 140
                                      show_account, True)
    
    132 141
                     self._ui.listbox.add(row)
    
    133 142
     
    
    143
    +    def _on_page_changed(self, stack, _param):
    
    144
    +        if stack.get_visible_child_name() == 'account':
    
    145
    +            self._ui.account_view.grab_focus()
    
    146
    +
    
    134 147
         def _on_row_activated(self, _listbox, row):
    
    135
    -        row = row.get_child()
    
    136
    -        self._start_new_chat(row)
    
    148
    +        if self._current_listbox_is(Search.GLOBAL):
    
    149
    +            self._select_muc()
    
    150
    +        else:
    
    151
    +            self._start_new_chat(row)
    
    152
    +
    
    153
    +    def _select_muc(self):
    
    154
    +        if len(self._accounts) > 1:
    
    155
    +            self._ui.stack.set_visible_child_name('account')
    
    156
    +        else:
    
    157
    +            self._on_select_clicked()
    
    137 158
     
    
    138 159
         def _on_key_press(self, _widget, event):
    
    139 160
             is_search = self._ui.stack.get_visible_child_name() == 'search'
    
    140 161
             if event.keyval in (Gdk.KEY_Down, Gdk.KEY_Tab):
    
    141
    -            if is_search:
    
    162
    +            if not is_search:
    
    163
    +                return Gdk.EVENT_PROPAGATE
    
    164
    +
    
    165
    +            if self._global_search_active():
    
    166
    +                self._global_search_listbox.select_next()
    
    167
    +            else:
    
    142 168
                     self._ui.search_entry.emit('next-match')
    
    143
    -                return Gdk.EVENT_STOP
    
    144
    -            return Gdk.EVENT_PROPAGATE
    
    169
    +            return Gdk.EVENT_STOP
    
    145 170
     
    
    146 171
             if (event.state == Gdk.ModifierType.SHIFT_MASK and
    
    147 172
                     event.keyval == Gdk.KEY_ISO_Left_Tab):
    
    148
    -            if is_search:
    
    173
    +            if not is_search:
    
    174
    +                return Gdk.EVENT_PROPAGATE
    
    175
    +
    
    176
    +            if self._global_search_active():
    
    177
    +                self._global_search_listbox.select_prev()
    
    178
    +            else:
    
    149 179
                     self._ui.search_entry.emit('previous-match')
    
    150
    -                return Gdk.EVENT_STOP
    
    151
    -            return Gdk.EVENT_PROPAGATE
    
    180
    +            return Gdk.EVENT_STOP
    
    152 181
     
    
    153 182
             if event.keyval == Gdk.KEY_Up:
    
    154
    -            if is_search:
    
    183
    +            if not is_search:
    
    184
    +                return Gdk.EVENT_PROPAGATE
    
    185
    +
    
    186
    +            if self._global_search_active():
    
    187
    +                self._global_search_listbox.select_prev()
    
    188
    +            else:
    
    155 189
                     self._ui.search_entry.emit('previous-match')
    
    156
    -                return Gdk.EVENT_STOP
    
    157
    -            return Gdk.EVENT_PROPAGATE
    
    190
    +            return Gdk.EVENT_STOP
    
    158 191
     
    
    159 192
             if event.keyval == Gdk.KEY_Escape:
    
    160 193
                 if self._ui.stack.get_visible_child_name() == 'progress':
    
    161 194
                     self.destroy()
    
    162 195
                     return Gdk.EVENT_STOP
    
    163 196
     
    
    197
    +            if self._ui.stack.get_visible_child_name() == 'account':
    
    198
    +                self._on_back_clicked()
    
    199
    +                return Gdk.EVENT_STOP
    
    200
    +
    
    164 201
                 if self._ui.stack.get_visible_child_name() in ('error', 'info'):
    
    165 202
                     self._ui.stack.set_visible_child_name('search')
    
    166 203
                     return Gdk.EVENT_STOP
    
    167 204
     
    
    168 205
                 self._search_stopped = True
    
    169
    -            self._muc_search_listbox.remove_all()
    
    206
    +            self._ui.search_entry.grab_focus()
    
    207
    +            self._scroll_to_first_row()
    
    208
    +            self._global_search_listbox.remove_all()
    
    170 209
                 if self._ui.search_entry.get_text() != '':
    
    171 210
                     self._ui.search_entry.emit('stop-search')
    
    172 211
                 else:
    
    ... ... @@ -177,6 +216,10 @@ class StartChatDialog(Gtk.ApplicationWindow):
    177 216
                 if self._ui.stack.get_visible_child_name() == 'progress':
    
    178 217
                     return Gdk.EVENT_STOP
    
    179 218
     
    
    219
    +            if self._ui.stack.get_visible_child_name() == 'account':
    
    220
    +                self._on_select_clicked()
    
    221
    +                return Gdk.EVENT_STOP
    
    222
    +
    
    180 223
                 if self._ui.stack.get_visible_child_name() == 'error':
    
    181 224
                     self._ui.stack.set_visible_child_name('search')
    
    182 225
                     return Gdk.EVENT_STOP
    
    ... ... @@ -185,9 +228,13 @@ class StartChatDialog(Gtk.ApplicationWindow):
    185 228
                     self._on_join_clicked()
    
    186 229
                     return Gdk.EVENT_STOP
    
    187 230
     
    
    188
    -            if self._current_listbox_is(Search.MUC):
    
    189
    -                self._muc_search_listbox.remove_all()
    
    190
    -                self._start_search()
    
    231
    +            if self._current_listbox_is(Search.GLOBAL):
    
    232
    +                if self._ui.search_entry.is_focus():
    
    233
    +                    self._global_search_listbox.remove_all()
    
    234
    +                    self._start_search()
    
    235
    +
    
    236
    +                elif self._global_search_listbox.get_selected_row() is not None:
    
    237
    +                    self._select_muc()
    
    191 238
                     return Gdk.EVENT_STOP
    
    192 239
     
    
    193 240
                 row = self._ui.listbox.get_selected_row()
    
    ... ... @@ -204,7 +251,7 @@ class StartChatDialog(Gtk.ApplicationWindow):
    204 251
                 try:
    
    205 252
                     JID(row.jid)
    
    206 253
                 except InvalidJid as error:
    
    207
    -                self._show_error_page(str(error))
    
    254
    +                self._show_error_page(error)
    
    208 255
                     return
    
    209 256
     
    
    210 257
             if row.groupchat:
    
    ... ... @@ -215,8 +262,7 @@ class StartChatDialog(Gtk.ApplicationWindow):
    215 262
                 self._disco_muc(row.account, row.jid)
    
    216 263
             else:
    
    217 264
                 app.interface.new_chat_from_jid(row.account, row.jid)
    
    218
    -
    
    219
    -        self.ready_to_destroy = True
    
    265
    +            self.ready_to_destroy = True
    
    220 266
     
    
    221 267
         def _disco_muc(self, account, jid):
    
    222 268
             self._ui.stack.set_visible_child_name('progress')
    
    ... ... @@ -245,17 +291,37 @@ class StartChatDialog(Gtk.ApplicationWindow):
    245 291
             self._show_error_page(MUC_DISCO_ERRORS[error_code])
    
    246 292
     
    
    247 293
         def _show_error_page(self, text):
    
    248
    -        self._ui.error_label.set_text(text)
    
    294
    +        self._ui.error_label.set_text(str(text))
    
    249 295
             self._ui.stack.set_visible_child_name('error')
    
    250 296
     
    
    251 297
         def _on_join_clicked(self, _button=None):
    
    252
    -        row = self._ui.listbox.get_selected_row().get_child()
    
    253
    -        app.interface.join_gc_minimal(row.account, row.jid)
    
    298
    +        account = self._muc_info_box.get_account()
    
    299
    +        jid = self._muc_info_box.get_jid()
    
    300
    +        app.interface.join_gc_minimal(account, str(jid))
    
    254 301
             self.ready_to_destroy = True
    
    255 302
     
    
    256
    -    def _on_back_clicked(self, _button):
    
    303
    +    def _on_back_clicked(self, _button=None):
    
    257 304
             self._ui.stack.set_visible_child_name('search')
    
    258 305
     
    
    306
    +    def _on_select_clicked(self, _button=None):
    
    307
    +        model, iter_ = self._ui.account_view.get_selection().get_selected()
    
    308
    +        if iter_ is not None:
    
    309
    +            account = model[iter_][1]
    
    310
    +        elif len(self._accounts) == 1:
    
    311
    +            account = self._accounts[0][0]
    
    312
    +        else:
    
    313
    +            return
    
    314
    +
    
    315
    +        selected_row = self._global_search_listbox.get_selected_row()
    
    316
    +        if selected_row is None:
    
    317
    +            return
    
    318
    +
    
    319
    +        if not app.account_is_connected(account):
    
    320
    +            self._show_error_page(_('You can not join a group chat '
    
    321
    +                                    'unless you are connected.'))
    
    322
    +            return
    
    323
    +        self._disco_muc(account, selected_row.jid)
    
    324
    +
    
    259 325
         def _set_listbox(self, listbox):
    
    260 326
             if self._current_listbox == listbox:
    
    261 327
                 return
    
    ... ... @@ -268,15 +334,24 @@ class StartChatDialog(Gtk.ApplicationWindow):
    268 334
         def _current_listbox_is(self, box):
    
    269 335
             if self._current_listbox == self._ui.listbox:
    
    270 336
                 return box == Search.CONTACT
    
    271
    -        return box == Search.MUC
    
    337
    +        return box == Search.GLOBAL
    
    338
    +
    
    339
    +    def _on_global_search_toggle(self, button):
    
    340
    +        self._ui.search_entry.set_text('')
    
    341
    +        self._ui.search_entry.grab_focus()
    
    342
    +        if button.get_active():
    
    343
    +            self._set_listbox(self._global_search_listbox)
    
    344
    +            self._remove_new_jid_row()
    
    345
    +            self._ui.listbox.invalidate_filter()
    
    346
    +        else:
    
    347
    +            self._set_listbox(self._ui.listbox)
    
    348
    +            self._global_search_listbox.remove_all()
    
    272 349
     
    
    273 350
         def _on_search_changed(self, entry):
    
    274
    -        search_text = entry.get_text()
    
    275
    -        if search_text.startswith('g:'):
    
    276
    -            self._set_listbox(self._muc_search_listbox)
    
    351
    +        if self._global_search_active():
    
    277 352
                 return
    
    278 353
     
    
    279
    -        self._set_listbox(self._ui.listbox)
    
    354
    +        search_text = entry.get_text()
    
    280 355
             if '@' in search_text:
    
    281 356
                 self._add_new_jid_row()
    
    282 357
                 self._update_new_jid_rows(search_text)
    
    ... ... @@ -288,7 +363,7 @@ class StartChatDialog(Gtk.ApplicationWindow):
    288 363
             if self.new_contact_row_visible:
    
    289 364
                 return
    
    290 365
             for account in self.new_contact_rows:
    
    291
    -            show_account = len(self.accounts) > 1
    
    366
    +            show_account = len(self._accounts) > 1
    
    292 367
                 row = ContactRow(account, None, '', None, show_account)
    
    293 368
                 self.new_contact_rows[account] = row
    
    294 369
                 group_row = ContactRow(account, None, '', None, show_account, True)
    
    ... ... @@ -342,10 +417,13 @@ class StartChatDialog(Gtk.ApplicationWindow):
    342 417
             first_row = self._ui.listbox.get_row_at_y(0)
    
    343 418
             self._ui.listbox.select_row(first_row)
    
    344 419
     
    
    420
    +    def _scroll_to_first_row(self):
    
    421
    +        self._ui.scrolledwindow.get_vadjustment().set_value(0)
    
    422
    +
    
    345 423
         def _filter_func(self, row, _user_data):
    
    346 424
             search_text = self._ui.search_entry.get_text().lower()
    
    347 425
             search_text_list = search_text.split()
    
    348
    -        row_text = row.get_child().get_search_text().lower()
    
    426
    +        row_text = row.get_search_text().lower()
    
    349 427
             for text in search_text_list:
    
    350 428
                 if text not in row_text:
    
    351 429
                     GLib.timeout_add(50, self.select_first_row)
    
    ... ... @@ -355,14 +433,14 @@ class StartChatDialog(Gtk.ApplicationWindow):
    355 433
     
    
    356 434
         @staticmethod
    
    357 435
         def _sort_func(row1, row2, _user_data):
    
    358
    -        name1 = row1.get_child().get_search_text()
    
    359
    -        name2 = row2.get_child().get_search_text()
    
    360
    -        account1 = row1.get_child().account
    
    361
    -        account2 = row2.get_child().account
    
    362
    -        is_groupchat1 = row1.get_child().groupchat
    
    363
    -        is_groupchat2 = row2.get_child().groupchat
    
    364
    -        new1 = row1.get_child().new
    
    365
    -        new2 = row2.get_child().new
    
    436
    +        name1 = row1.get_search_text()
    
    437
    +        name2 = row2.get_search_text()
    
    438
    +        account1 = row1.account
    
    439
    +        account2 = row2.account
    
    440
    +        is_groupchat1 = row1.groupchat
    
    441
    +        is_groupchat2 = row2.groupchat
    
    442
    +        new1 = row1.new
    
    443
    +        new2 = row2.new
    
    366 444
     
    
    367 445
             result = locale.strcoll(account1.lower(), account2.lower())
    
    368 446
             if result != 0:
    
    ... ... @@ -376,23 +454,15 @@ class StartChatDialog(Gtk.ApplicationWindow):
    376 454
     
    
    377 455
             return locale.strcoll(name1.lower(), name2.lower())
    
    378 456
     
    
    379
    -    @staticmethod
    
    380
    -    def _get_connection():
    
    381
    -        accounts = app.get_connected_accounts()
    
    382
    -        if not accounts:
    
    383
    -            raise NotConnected
    
    384
    -        return app.connections[accounts.pop()].connection
    
    385
    -
    
    386 457
         def _start_search(self):
    
    387 458
             self._search_stopped = False
    
    388
    -        try:
    
    389
    -            con = self._get_connection()
    
    390
    -        except NotConnected:
    
    459
    +        accounts = app.get_connected_accounts()
    
    460
    +        if not accounts:
    
    391 461
                 return
    
    462
    +        con = app.connections[accounts[0]].connection
    
    392 463
     
    
    393
    -        text = self._ui.search_entry.get_text()
    
    394
    -        text = text[2:].strip()
    
    395
    -        self._muc_search_listbox.start_search()
    
    464
    +        text = self._ui.search_entry.get_text().strip()
    
    465
    +        self._global_search_listbox.start_search()
    
    396 466
     
    
    397 467
             if self._parameter_form is None:
    
    398 468
                 con.get_module('Muclumbus').request_parameters(
    
    ... ... @@ -411,7 +481,8 @@ class StartChatDialog(Gtk.ApplicationWindow):
    411 481
         @ensure_not_destroyed
    
    412 482
         def _parameters_received(self, result, user_data):
    
    413 483
             if is_error_result(result):
    
    414
    -            self._on_error(result)
    
    484
    +            self._global_search_listbox.remove_progress()
    
    485
    +            self._show_error_page(result.message)
    
    415 486
                 return
    
    416 487
     
    
    417 488
             con, text = user_data
    
    ... ... @@ -431,14 +502,15 @@ class StartChatDialog(Gtk.ApplicationWindow):
    431 502
                 return
    
    432 503
     
    
    433 504
             if is_error_result(result):
    
    434
    -            self._on_error(result)
    
    505
    +            self._global_search_listbox.remove_progress()
    
    506
    +            self._show_error_page(result.message)
    
    435 507
                 return
    
    436 508
     
    
    437 509
             for item in result.items:
    
    438
    -            self._muc_search_listbox.add(ResultRow(item))
    
    510
    +            self._global_search_listbox.add(ResultRow(item))
    
    439 511
     
    
    440 512
             if result.end:
    
    441
    -            self._muc_search_listbox.end_search()
    
    513
    +            self._global_search_listbox.end_search()
    
    442 514
                 return
    
    443 515
     
    
    444 516
             con.get_module('Muclumbus').set_search(
    
    ... ... @@ -449,19 +521,15 @@ class StartChatDialog(Gtk.ApplicationWindow):
    449 521
                 callback=self._on_search_result,
    
    450 522
                 user_data=con)
    
    451 523
     
    
    452
    -    def _on_error(self, result):
    
    453
    -        self._muc_search_listbox.show_error(result)
    
    454
    -
    
    455 524
         def _destroy(self, *args):
    
    456 525
             self._destroyed = True
    
    457 526
     
    
    458 527
     
    
    459
    -class ContactRow(Gtk.Grid):
    
    528
    +class ContactRow(Gtk.ListBoxRow):
    
    460 529
         def __init__(self, account, contact, jid, name, show_account,
    
    461 530
                      groupchat=False):
    
    462
    -        Gtk.Grid.__init__(self)
    
    463
    -        self.set_column_spacing(12)
    
    464
    -        self.set_size_request(260, -1)
    
    531
    +        Gtk.ListBoxRow.__init__(self)
    
    532
    +        self.get_style_context().add_class('start-chat-row')
    
    465 533
             self.account = account
    
    466 534
             self.account_label = app.get_account_label(account)
    
    467 535
             self.show_account = show_account
    
    ... ... @@ -471,6 +539,11 @@ class ContactRow(Gtk.Grid):
    471 539
             self.groupchat = groupchat
    
    472 540
             self.new = jid == ''
    
    473 541
     
    
    542
    +
    
    543
    +        grid = Gtk.Grid()
    
    544
    +        grid.set_column_spacing(12)
    
    545
    +        grid.set_size_request(260, -1)
    
    546
    +
    
    474 547
             if self.groupchat:
    
    475 548
                 muc_icon = get_icon_name(
    
    476 549
                     'muc-inactive' if self.new else 'muc-active')
    
    ... ... @@ -486,7 +559,7 @@ class ContactRow(Gtk.Grid):
    486 559
                     image = Gtk.Image.new_from_surface(avatar)
    
    487 560
     
    
    488 561
             image.set_size_request(AvatarSize.CHAT, AvatarSize.CHAT)
    
    489
    -        self.add(image)
    
    562
    +        grid.add(image)
    
    490 563
     
    
    491 564
             middle_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
    
    492 565
             middle_box.set_hexpand(True)
    
    ... ... @@ -518,7 +591,7 @@ class ContactRow(Gtk.Grid):
    518 591
             self.jid_label.get_style_context().add_class('dim-label')
    
    519 592
             middle_box.add(self.jid_label)
    
    520 593
     
    
    521
    -        self.add(middle_box)
    
    594
    +        grid.add(middle_box)
    
    522 595
     
    
    523 596
             if show_account:
    
    524 597
                 account_label = Gtk.Label(label=self.account_label)
    
    ... ... @@ -528,8 +601,9 @@ class ContactRow(Gtk.Grid):
    528 601
                 right_box = Gtk.Box()
    
    529 602
                 right_box.set_vexpand(True)
    
    530 603
                 right_box.add(account_label)
    
    531
    -            self.add(right_box)
    
    604
    +            grid.add(right_box)
    
    532 605
     
    
    606
    +        self.add(grid)
    
    533 607
             self.show_all()
    
    534 608
     
    
    535 609
         def update_jid(self, jid):
    
    ... ... @@ -544,16 +618,12 @@ class ContactRow(Gtk.Grid):
    544 618
             return '%s %s' % (self.name, self.jid)
    
    545 619
     
    
    546 620
     
    
    547
    -class MUCSearch(Gtk.ListBox):
    
    621
    +class GlobalSearch(Gtk.ListBox):
    
    548 622
         def __init__(self):
    
    549 623
             Gtk.ListBox.__init__(self)
    
    550 624
             self.set_has_tooltip(True)
    
    551 625
             self.set_activate_on_single_click(False)
    
    552 626
             self._progress = None
    
    553
    -
    
    554
    -        self._ui = get_builder('start_chat_dialog.ui', ['tooltip'])
    
    555
    -        self.connect('query-tooltip', self._query_tooltip)
    
    556
    -        self.connect('row-activated', self._on_row_activated)
    
    557 627
             self.show_all()
    
    558 628
     
    
    559 629
         def remove_all(self):
    
    ... ... @@ -562,8 +632,7 @@ class MUCSearch(Gtk.ListBox):
    562 632
                 row.destroy()
    
    563 633
             self.foreach(remove)
    
    564 634
     
    
    565
    -    def show_error(self, error):
    
    566
    -        self.insert(ErrorRow(error), 0)
    
    635
    +    def remove_progress(self):
    
    567 636
             self.remove(self._progress)
    
    568 637
             self._progress.destroy()
    
    569 638
     
    
    ... ... @@ -576,44 +645,36 @@ class MUCSearch(Gtk.ListBox):
    576 645
     
    
    577 646
         def add(self, row):
    
    578 647
             super().add(row)
    
    648
    +        if self.get_selected_row() is None:
    
    649
    +            row = self.get_row_at_index(1)
    
    650
    +            if row is not None:
    
    651
    +                self.select_row(row)
    
    652
    +                row.grab_focus()
    
    579 653
             self._progress.update()
    
    580 654
     
    
    581
    -    def _query_tooltip(self, _widget, _x_pos, y_pos, _keyboard_mode, tooltip):
    
    582
    -        row = self.get_row_at_y(y_pos)
    
    583
    -        if row is None or not isinstance(row, ResultRow):
    
    584
    -            self._clear_tooltip()
    
    585
    -            return False
    
    586
    -
    
    587
    -        if row.item.anonymity_mode == AnonymityMode.SEMI:
    
    588
    -            self._ui.anonymous_icon.show()
    
    589
    -            self._ui.anonymous_label.show()
    
    590
    -
    
    591
    -        self._ui.tooltip_user.set_text(row.item.nusers)
    
    592
    -        self._ui.tooltip_jid.set_text(row.item.jid)
    
    593
    -        if row.item.description:
    
    594
    -            self._ui.tooltip_description.set_text(row.item.description)
    
    595
    -            self._ui.tooltip_description.show()
    
    596
    -            self._ui.tooltip_description_label.show()
    
    597
    -
    
    598
    -        if row.item.name:
    
    599
    -            self._ui.tooltip_name.set_text(row.item.name)
    
    600
    -            self._ui.tooltip_name.show()
    
    601
    -            self._ui.tooltip_name_label.show()
    
    602
    -
    
    603
    -        tooltip.set_custom(self._ui.tooltip)
    
    604
    -        return True
    
    655
    +    def _select(self, direction):
    
    656
    +        selected_row = self.get_selected_row()
    
    657
    +        if selected_row is None:
    
    658
    +            return
    
    605 659
     
    
    606
    -    def _clear_tooltip(self):
    
    607
    -        self._ui.anonymous_icon.hide()
    
    608
    -        self._ui.anonymous_label.hide()
    
    609
    -        self._ui.tooltip_description.hide()
    
    610
    -        self._ui.tooltip_description_label.hide()
    
    611
    -        self._ui.tooltip_name.hide()
    
    612
    -        self._ui.tooltip_name_label.hide()
    
    660
    +        index = selected_row.get_index()
    
    661
    +        if direction == 'next':
    
    662
    +            index += 1
    
    663
    +        else:
    
    664
    +            index -= 1
    
    613 665
     
    
    614
    -    @staticmethod
    
    615
    -    def _on_row_activated(_listbox, row):
    
    616
    -        app.interface.join_gc_minimal(None, row.item.jid)
    
    666
    +        new_selected_row = self.get_row_at_index(index)
    
    667
    +        if new_selected_row is None:
    
    668
    +            return
    
    669
    +
    
    670
    +        self.select_row(new_selected_row)
    
    671
    +        new_selected_row.grab_focus()
    
    672
    +
    
    673
    +    def select_next(self):
    
    674
    +        self._select('next')
    
    675
    +
    
    676
    +    def select_prev(self):
    
    677
    +        self._select('prev')
    
    617 678
     
    
    618 679
     
    
    619 680
     class ResultRow(Gtk.ListBoxRow):
    
    ... ... @@ -621,33 +682,23 @@ class ResultRow(Gtk.ListBoxRow):
    621 682
             Gtk.ListBoxRow.__init__(self)
    
    622 683
             self.set_activatable(True)
    
    623 684
             self.get_style_context().add_class('start-chat-row')
    
    624
    -        self.item = item
    
    625
    -        self._ui = get_builder('start_chat_dialog.ui', ['search_result_grid'])
    
    626
    -        self._ui.jid_label.set_text(item.jid)
    
    627
    -        self._ui.name_label.set_text(item.name)
    
    628
    -        self._ui.user_label.set_text(item.nusers)
    
    629
    -        self.add(self._ui.search_result_grid)
    
    630
    -        self.show_all()
    
    685
    +        self.new = False
    
    686
    +        self.jid = item.jid
    
    687
    +        self.groupchat = True
    
    688
    +
    
    689
    +        name_label = Gtk.Label(label=item.name)
    
    690
    +        name_label.set_halign(Gtk.Align.START)
    
    691
    +        name_label.set_ellipsize(Pango.EllipsizeMode.END)
    
    692
    +        name_label.set_max_width_chars(40)
    
    693
    +        name_label.get_style_context().add_class('bold16')
    
    694
    +        jid_label = Gtk.Label(label=item.jid)
    
    695
    +        jid_label.set_halign(Gtk.Align.START)
    
    696
    +        jid_label.set_ellipsize(Pango.EllipsizeMode.END)
    
    697
    +        jid_label.set_max_width_chars(40)
    
    698
    +        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
    
    699
    +        box.add(name_label)
    
    700
    +        box.add(jid_label)
    
    631 701
     
    
    632
    -
    
    633
    -class ErrorRow(Gtk.ListBoxRow):
    
    634
    -    def __init__(self, error):
    
    635
    -        Gtk.ListBoxRow.__init__(self)
    
    636
    -        self.set_selectable(False)
    
    637
    -        self.set_activatable(False)
    
    638
    -        self.get_style_context().add_class('start-chat-row')
    
    639
    -        self._error = Gtk.Label(label=str(error))
    
    640
    -        self._error.set_line_wrap(True)
    
    641
    -        self._error.set_line_wrap_mode(Pango.WrapMode.WORD)
    
    642
    -        self._error.set_xalign(0)
    
    643
    -        self._error_image = Gtk.Image.new_from_icon_name(
    
    644
    -            'dialog-error', Gtk.IconSize.MENU)
    
    645
    -        self._error_image.get_style_context().add_class('error-color')
    
    646
    -        self._error_image.set_valign(Gtk.Align.CENTER)
    
    647
    -        box = Gtk.Box()
    
    648
    -        box.set_spacing(6)
    
    649
    -        box.add(self._error_image)
    
    650
    -        box.add(self._error)
    
    651 702
             self.add(box)
    
    652 703
             self.show_all()
    
    653 704
     
    
    ... ... @@ -685,7 +736,3 @@ class ProgressRow(Gtk.ListBoxRow):
    685 736
             self._spinner.stop()
    
    686 737
             self._spinner.hide()
    
    687 738
             self._finished_image.show()
    688
    -
    
    689
    -
    
    690
    -class NotConnected(Exception):
    
    691
    -    pass