New StartChat Dialog
This commit is contained in:
		
							parent
							
								
									010b166fd2
								
							
						
					
					
						commit
						1afd4f0e72
					
				
					 13 changed files with 402 additions and 69 deletions
				
			
		| 
						 | 
				
			
			@ -80,6 +80,12 @@ class AppActions():
 | 
			
		|||
    def on_quit(self, action, param):
 | 
			
		||||
        interface.roster.on_quit_request()
 | 
			
		||||
 | 
			
		||||
    def on_new_chat(self, action, param):
 | 
			
		||||
        if 'start_chat' in app.interface.instances:
 | 
			
		||||
            app.interface.instances['start_chat'].present()
 | 
			
		||||
        else:
 | 
			
		||||
            app.interface.instances['start_chat'] = dialogs.StartChatDialog()
 | 
			
		||||
 | 
			
		||||
    # Accounts Actions
 | 
			
		||||
 | 
			
		||||
    def on_profile(self, action, param):
 | 
			
		||||
| 
						 | 
				
			
			@ -130,9 +136,6 @@ class AppActions():
 | 
			
		|||
    def on_add_contact(self, action, param):
 | 
			
		||||
        dialogs.AddNewContactWindow(param.get_string())
 | 
			
		||||
 | 
			
		||||
    def on_new_chat(self, action, param):
 | 
			
		||||
        dialogs.NewChatDialog(param.get_string())
 | 
			
		||||
 | 
			
		||||
    def on_single_message(self, action, param):
 | 
			
		||||
        dialogs.SingleMessageWindow(param.get_string(), action='send')
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -411,6 +411,16 @@ def get_uf_show(show, use_mnemonic = False):
 | 
			
		|||
        uf_show = Q_('?contact has status:Has errors')
 | 
			
		||||
    return uf_show
 | 
			
		||||
 | 
			
		||||
def get_css_show_color(show):
 | 
			
		||||
    if show in ('online', 'chat', 'invisible'):
 | 
			
		||||
        return 'status-online'
 | 
			
		||||
    elif show in ('offline', 'not in roster', 'requested'):
 | 
			
		||||
        return None
 | 
			
		||||
    elif show in ('xa', 'dnd'):
 | 
			
		||||
        return 'status-dnd'
 | 
			
		||||
    elif show in ('away'):
 | 
			
		||||
        return 'status-away'
 | 
			
		||||
 | 
			
		||||
def get_uf_sub(sub):
 | 
			
		||||
    if sub == 'none':
 | 
			
		||||
        uf_sub = Q_('?Subscription we already have:None')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,15 +28,6 @@
 | 
			
		|||
        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
 | 
			
		||||
      </object>
 | 
			
		||||
    </child>
 | 
			
		||||
    <child>
 | 
			
		||||
      <object class="GtkMenuItem" id="start_chat_menuitem">
 | 
			
		||||
        <property name="visible">True</property>
 | 
			
		||||
        <property name="can_focus">False</property>
 | 
			
		||||
        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
 | 
			
		||||
        <property name="label" translatable="yes">_Start Chat...</property>
 | 
			
		||||
        <property name="use_underline">True</property>
 | 
			
		||||
      </object>
 | 
			
		||||
    </child>
 | 
			
		||||
    <child>
 | 
			
		||||
      <object class="GtkMenuItem" id="join_group_chat_menuitem">
 | 
			
		||||
        <property name="visible">True</property>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,6 +72,11 @@
 | 
			
		|||
        <attribute name="action">app.accounts</attribute>
 | 
			
		||||
        <attribute name="accel"><Primary><Shift>A</attribute>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
        <attribute name="label" translatable="yes">Start Chat</attribute>
 | 
			
		||||
        <attribute name="action">app.start-chat</attribute>
 | 
			
		||||
        <attribute name="accel"><Primary>N</attribute>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
        <attribute name="label" translatable="yes">Bookmarks</attribute>
 | 
			
		||||
        <attribute name="action">app.bookmarks</attribute>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										56
									
								
								gajim/data/gui/start_chat_dialog.ui
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								gajim/data/gui/start_chat_dialog.ui
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,56 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!-- Generated with glade 3.20.1 -->
 | 
			
		||||
<interface>
 | 
			
		||||
  <requires lib="gtk+" version="3.20"/>
 | 
			
		||||
  <object class="GtkBox" id="box">
 | 
			
		||||
    <property name="visible">True</property>
 | 
			
		||||
    <property name="can_focus">False</property>
 | 
			
		||||
    <property name="border_width">18</property>
 | 
			
		||||
    <property name="orientation">vertical</property>
 | 
			
		||||
    <property name="spacing">6</property>
 | 
			
		||||
    <child>
 | 
			
		||||
      <object class="GtkSearchEntry" id="search_entry">
 | 
			
		||||
        <property name="visible">True</property>
 | 
			
		||||
        <property name="can_focus">True</property>
 | 
			
		||||
        <property name="has_focus">True</property>
 | 
			
		||||
        <property name="is_focus">True</property>
 | 
			
		||||
        <property name="primary_icon_name">edit-find-symbolic</property>
 | 
			
		||||
        <property name="primary_icon_activatable">False</property>
 | 
			
		||||
        <property name="primary_icon_sensitive">False</property>
 | 
			
		||||
      </object>
 | 
			
		||||
      <packing>
 | 
			
		||||
        <property name="expand">False</property>
 | 
			
		||||
        <property name="fill">True</property>
 | 
			
		||||
        <property name="position">0</property>
 | 
			
		||||
      </packing>
 | 
			
		||||
    </child>
 | 
			
		||||
    <child>
 | 
			
		||||
      <object class="GtkScrolledWindow">
 | 
			
		||||
        <property name="visible">True</property>
 | 
			
		||||
        <property name="can_focus">True</property>
 | 
			
		||||
        <property name="hscrollbar_policy">never</property>
 | 
			
		||||
        <property name="shadow_type">in</property>
 | 
			
		||||
        <child>
 | 
			
		||||
          <object class="GtkViewport">
 | 
			
		||||
            <property name="visible">True</property>
 | 
			
		||||
            <property name="can_focus">False</property>
 | 
			
		||||
            <child>
 | 
			
		||||
              <object class="GtkListBox" id="listbox">
 | 
			
		||||
                <property name="name">StartChatListBox</property>
 | 
			
		||||
                <property name="visible">True</property>
 | 
			
		||||
                <property name="can_focus">False</property>
 | 
			
		||||
                <property name="selection_mode">browse</property>
 | 
			
		||||
                <property name="activate_on_single_click">False</property>
 | 
			
		||||
              </object>
 | 
			
		||||
            </child>
 | 
			
		||||
          </object>
 | 
			
		||||
        </child>
 | 
			
		||||
      </object>
 | 
			
		||||
      <packing>
 | 
			
		||||
        <property name="expand">True</property>
 | 
			
		||||
        <property name="fill">True</property>
 | 
			
		||||
        <property name="position">1</property>
 | 
			
		||||
      </packing>
 | 
			
		||||
    </child>
 | 
			
		||||
  </object>
 | 
			
		||||
</interface>
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +86,16 @@ popover#EmoticonPopover flowboxchild { padding-top: 5px; padding-bottom: 5px; }
 | 
			
		|||
                             background-color: @theme_unfocused_bg_color;
 | 
			
		||||
                             color: @theme_text_color; }
 | 
			
		||||
 | 
			
		||||
/* StartChatListBox */
 | 
			
		||||
#StartChatListBox > row { border-bottom: 1px solid; border-color: @theme_unfocused_bg_color; }
 | 
			
		||||
#StartChatListBox > row:last-child { border-bottom: 0px}
 | 
			
		||||
#StartChatListBox > row.activatable:active { box-shadow: none; }
 | 
			
		||||
#StartChatListBox > row { padding: 10px 20px 10px 10px; }
 | 
			
		||||
#StartChatListBox > row:not(.activatable) label { color: @insensitive_fg_color }
 | 
			
		||||
 | 
			
		||||
/* Text style */
 | 
			
		||||
 | 
			
		||||
.bold16 { font-size: 16px; font-weight: bold; }
 | 
			
		||||
.status-away { color: #ff8533;}
 | 
			
		||||
.status-dnd { color: #e62e00;}
 | 
			
		||||
.status-online { color: #66bf10;}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										350
									
								
								gajim/dialogs.py
									
										
									
									
									
								
							
							
						
						
									
										350
									
								
								gajim/dialogs.py
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -38,6 +38,7 @@ from gi.repository import GLib
 | 
			
		|||
import os
 | 
			
		||||
import nbxmpp
 | 
			
		||||
import time
 | 
			
		||||
import locale
 | 
			
		||||
 | 
			
		||||
from gajim import gtkgui_helpers
 | 
			
		||||
from gajim import vcard
 | 
			
		||||
| 
						 | 
				
			
			@ -61,6 +62,7 @@ from gajim.common import app
 | 
			
		|||
from gajim.common import helpers
 | 
			
		||||
from gajim.common import i18n
 | 
			
		||||
from gajim.common import dataforms
 | 
			
		||||
from gajim.common.const import AvatarSize
 | 
			
		||||
from gajim.common.caps_cache import muc_caps_cache
 | 
			
		||||
from gajim.common.exceptions import GajimGeneralException
 | 
			
		||||
from gajim.common.connection_handlers_events import MessageOutgoingEvent
 | 
			
		||||
| 
						 | 
				
			
			@ -2757,59 +2759,323 @@ class SynchroniseSelectContactsDialog:
 | 
			
		|||
            iter_ = model.iter_next(iter_)
 | 
			
		||||
        self.dialog.destroy()
 | 
			
		||||
 | 
			
		||||
class NewChatDialog(InputDialog):
 | 
			
		||||
    def __init__(self, account):
 | 
			
		||||
        self.account = account
 | 
			
		||||
class StartChatDialog(Gtk.ApplicationWindow):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        # Must be before ApplicationWindow.__init__
 | 
			
		||||
        # or we get our own window
 | 
			
		||||
        active_window = app.app.get_active_window()
 | 
			
		||||
 | 
			
		||||
        if len(app.connections) > 1:
 | 
			
		||||
            title = _('Start Chat with account %s') % account
 | 
			
		||||
        Gtk.ApplicationWindow.__init__(self)
 | 
			
		||||
        self.set_name('StartChatDialog')
 | 
			
		||||
        self.set_application(app.app)
 | 
			
		||||
        mode = app.config.get('one_message_window') != 'always_with_roster'
 | 
			
		||||
        if active_window == app.interface.roster.window and mode:
 | 
			
		||||
            self.set_position(Gtk.WindowPosition.CENTER)
 | 
			
		||||
        else:
 | 
			
		||||
            title = _('Start Chat')
 | 
			
		||||
        prompt_text = _('Fill in the nickname or the JID of the contact you '
 | 
			
		||||
        	'would like\nto send a chat message to:')
 | 
			
		||||
        InputDialog.__init__(self, title, prompt_text, is_modal=False)
 | 
			
		||||
        self.input_entry.set_placeholder_text(_('Nickname / JID'))
 | 
			
		||||
            self.set_transient_for(active_window)
 | 
			
		||||
            self.set_type_hint(Gdk.WindowTypeHint.DIALOG)
 | 
			
		||||
        self.set_show_menubar(False)
 | 
			
		||||
        self.set_title(_('Start new Conversation'))
 | 
			
		||||
        self.set_default_size(-1, 400)
 | 
			
		||||
 | 
			
		||||
        self.completion_dict = {}
 | 
			
		||||
        liststore = gtkgui_helpers.get_completion_liststore(self.input_entry)
 | 
			
		||||
        self.completion_dict = helpers.get_contact_dict_for_account(account)
 | 
			
		||||
        # add all contacts to the model
 | 
			
		||||
        keys = sorted(self.completion_dict.keys())
 | 
			
		||||
        for jid in keys:
 | 
			
		||||
            contact = self.completion_dict[jid]
 | 
			
		||||
            img = app.interface.jabber_state_images['16'][contact.show]
 | 
			
		||||
            liststore.append((img.get_pixbuf(), jid))
 | 
			
		||||
        self.builder = gtkgui_helpers.get_gtk_builder(
 | 
			
		||||
            'start_chat_dialog.ui')
 | 
			
		||||
        self.listbox = self.builder.get_object('listbox')
 | 
			
		||||
        self.search_entry = self.builder.get_object('search_entry')
 | 
			
		||||
        self.box = self.builder.get_object('box')
 | 
			
		||||
 | 
			
		||||
        self.ok_handler = self.new_chat_response
 | 
			
		||||
        okbutton = self.xml.get_object('okbutton')
 | 
			
		||||
        okbutton.connect('clicked', self.on_okbutton_clicked)
 | 
			
		||||
        cancelbutton = self.xml.get_object('cancelbutton')
 | 
			
		||||
        cancelbutton.connect('clicked', self.on_cancelbutton_clicked)
 | 
			
		||||
        self.dialog.set_transient_for(app.interface.roster.window)
 | 
			
		||||
        self.dialog.show_all()
 | 
			
		||||
        self.add(self.box)
 | 
			
		||||
 | 
			
		||||
    def new_chat_response(self, jid):
 | 
			
		||||
        """
 | 
			
		||||
        Called when ok button is clicked
 | 
			
		||||
        """
 | 
			
		||||
        if app.connections[self.account].connected <= 1:
 | 
			
		||||
            #if offline or connecting
 | 
			
		||||
            ErrorDialog(_('Connection not available'),
 | 
			
		||||
                _('Please make sure you are connected with "%s".') % self.account)
 | 
			
		||||
            return
 | 
			
		||||
        self.new_contact_row_visible = False
 | 
			
		||||
        self.new_contact_rows = {}
 | 
			
		||||
        self.new_groupchat_rows = {}
 | 
			
		||||
        self.accounts = app.connections.keys()
 | 
			
		||||
        self.add_contacts()
 | 
			
		||||
        self.add_groupchats()
 | 
			
		||||
 | 
			
		||||
        if jid in self.completion_dict:
 | 
			
		||||
            jid = self.completion_dict[jid].jid
 | 
			
		||||
        self.search_entry.connect('search-changed',
 | 
			
		||||
                                  self._on_search_changed)
 | 
			
		||||
        self.search_entry.connect('next-match',
 | 
			
		||||
                                  self._select_new_match, 'next')
 | 
			
		||||
        self.search_entry.connect('previous-match',
 | 
			
		||||
                                  self._select_new_match, 'prev')
 | 
			
		||||
        self.search_entry.connect('stop-search',
 | 
			
		||||
                                  lambda *args: self.search_entry.set_text(''))
 | 
			
		||||
 | 
			
		||||
        self.listbox.set_filter_func(self._filter_func, None)
 | 
			
		||||
        self.listbox.set_sort_func(self._sort_func, None)
 | 
			
		||||
        self.listbox.connect('row-activated', self._on_row_activated)
 | 
			
		||||
 | 
			
		||||
        self.connect('key-press-event', self._on_key_press)
 | 
			
		||||
        self.connect('destroy', self._destroy)
 | 
			
		||||
 | 
			
		||||
        self.select_first_row()
 | 
			
		||||
        self.show_all()
 | 
			
		||||
 | 
			
		||||
    def add_contacts(self):
 | 
			
		||||
        show_account = len(self.accounts) > 1
 | 
			
		||||
        for account in self.accounts:
 | 
			
		||||
            self.new_contact_rows[account] = None
 | 
			
		||||
            for jid in app.contacts.get_jid_list(account):
 | 
			
		||||
                contact = app.contacts.get_contact_with_highest_priority(
 | 
			
		||||
                    account, jid)
 | 
			
		||||
                if contact.is_groupchat():
 | 
			
		||||
                    continue
 | 
			
		||||
                row = ContactRow(account, contact, jid,
 | 
			
		||||
                                 contact.get_shown_name(), show_account)
 | 
			
		||||
                self.listbox.add(row)
 | 
			
		||||
 | 
			
		||||
    def add_groupchats(self):
 | 
			
		||||
        show_account = len(self.accounts) > 1
 | 
			
		||||
        for account in self.accounts:
 | 
			
		||||
            self.new_groupchat_rows[account] = None
 | 
			
		||||
            bookmarks = app.connections[account].bookmarks
 | 
			
		||||
            groupchats = {}
 | 
			
		||||
            for bookmark in bookmarks:
 | 
			
		||||
                groupchats[bookmark['jid']] = bookmark['name']
 | 
			
		||||
 | 
			
		||||
            for jid in app.contacts.get_gc_list(account):
 | 
			
		||||
                if jid in groupchats:
 | 
			
		||||
                    continue
 | 
			
		||||
                groupchats[jid] = None
 | 
			
		||||
 | 
			
		||||
            for jid in groupchats:
 | 
			
		||||
                name = groupchats[jid]
 | 
			
		||||
                if name is None:
 | 
			
		||||
                    name = app.get_nick_from_jid(groupchats[jid])
 | 
			
		||||
                row = ContactRow(account, None, jid, name,
 | 
			
		||||
                                 show_account, True)
 | 
			
		||||
                self.listbox.add(row)
 | 
			
		||||
 | 
			
		||||
    def _on_row_activated(self, listbox, row):
 | 
			
		||||
        row = row.get_child()
 | 
			
		||||
        self._start_new_chat(row)
 | 
			
		||||
 | 
			
		||||
    def _on_key_press(self, widget, event):
 | 
			
		||||
        if event.keyval in (Gdk.KEY_Down, Gdk.KEY_Tab):
 | 
			
		||||
            self.search_entry.emit('next-match')
 | 
			
		||||
            return True
 | 
			
		||||
        elif (event.state == Gdk.ModifierType.SHIFT_MASK and
 | 
			
		||||
              event.keyval == Gdk.KEY_ISO_Left_Tab):
 | 
			
		||||
            self.search_entry.emit('previous-match')
 | 
			
		||||
            return True
 | 
			
		||||
        elif event.keyval == Gdk.KEY_Up:
 | 
			
		||||
            self.search_entry.emit('previous-match')
 | 
			
		||||
            return True
 | 
			
		||||
        elif event.keyval == Gdk.KEY_Escape:
 | 
			
		||||
            if self.search_entry.get_text() != '':
 | 
			
		||||
                self.search_entry.emit('stop-search')
 | 
			
		||||
            else:
 | 
			
		||||
                self.destroy()
 | 
			
		||||
            return True
 | 
			
		||||
        elif event.keyval == Gdk.KEY_Return:
 | 
			
		||||
            row = self.listbox.get_selected_row()
 | 
			
		||||
            if row is not None:
 | 
			
		||||
                row.emit('activate')
 | 
			
		||||
            return True
 | 
			
		||||
        else:
 | 
			
		||||
            self.search_entry.grab_focus_without_selecting()
 | 
			
		||||
 | 
			
		||||
    def _start_new_chat(self, row):
 | 
			
		||||
        if row.new:
 | 
			
		||||
            if not app.account_is_connected(row.account):
 | 
			
		||||
                ErrorDialog(
 | 
			
		||||
                    _('You are not connected to the server'),
 | 
			
		||||
                    _('You can not start a new conversation'
 | 
			
		||||
                      ' unless you are connected.'),
 | 
			
		||||
                    transient_for=self)
 | 
			
		||||
                return
 | 
			
		||||
            try:
 | 
			
		||||
                jid = helpers.parse_jid(jid)
 | 
			
		||||
                helpers.parse_jid(row.jid)
 | 
			
		||||
            except helpers.InvalidFormat as e:
 | 
			
		||||
                ErrorDialog(_('Invalid JID'), str(e))
 | 
			
		||||
                ErrorDialog(_('Invalid JID'), str(e), transient_for=self)
 | 
			
		||||
                return
 | 
			
		||||
            except:
 | 
			
		||||
                ErrorDialog(_('Invalid JID'), _('Unable to parse "%s".') % jid)
 | 
			
		||||
 | 
			
		||||
        if row.groupchat:
 | 
			
		||||
            app.interface.join_gc_minimal(row.account, row.jid)
 | 
			
		||||
        else:
 | 
			
		||||
            app.interface.new_chat_from_jid(row.account, row.jid)
 | 
			
		||||
 | 
			
		||||
        self.destroy()
 | 
			
		||||
 | 
			
		||||
    def _on_search_changed(self, entry):
 | 
			
		||||
        search_text = entry.get_text()
 | 
			
		||||
        if '@' in search_text:
 | 
			
		||||
            self._add_new_jid_row()
 | 
			
		||||
            self._update_new_jid_rows(search_text)
 | 
			
		||||
        else:
 | 
			
		||||
            self._remove_new_jid_row()
 | 
			
		||||
        self.listbox.invalidate_filter()
 | 
			
		||||
 | 
			
		||||
    def _add_new_jid_row(self):
 | 
			
		||||
        if self.new_contact_row_visible:
 | 
			
		||||
            return
 | 
			
		||||
        for account in self.new_contact_rows:
 | 
			
		||||
            show_account = len(self.accounts) > 1
 | 
			
		||||
            row = ContactRow(account, None, '', None, show_account)
 | 
			
		||||
            self.new_contact_rows[account] = row
 | 
			
		||||
            group_row = ContactRow(account, None, '', None, show_account, True)
 | 
			
		||||
            self.new_groupchat_rows[account] = group_row
 | 
			
		||||
            self.listbox.add(row)
 | 
			
		||||
            self.listbox.add(group_row)
 | 
			
		||||
            row.get_parent().show_all()
 | 
			
		||||
        self.new_contact_row_visible = True
 | 
			
		||||
 | 
			
		||||
    def _remove_new_jid_row(self):
 | 
			
		||||
        if not self.new_contact_row_visible:
 | 
			
		||||
            return
 | 
			
		||||
        for account in self.new_contact_rows:
 | 
			
		||||
            self.listbox.remove(self.new_contact_rows[account].get_parent())
 | 
			
		||||
            self.listbox.remove(self.new_groupchat_rows[account].get_parent())
 | 
			
		||||
        self.new_contact_row_visible = False
 | 
			
		||||
 | 
			
		||||
    def _update_new_jid_rows(self, search_text):
 | 
			
		||||
        for account in self.new_contact_rows:
 | 
			
		||||
            self.new_contact_rows[account].update_jid(search_text)
 | 
			
		||||
            self.new_groupchat_rows[account].update_jid(search_text)
 | 
			
		||||
 | 
			
		||||
    def _select_new_match(self, entry, direction):
 | 
			
		||||
        selected_row = self.listbox.get_selected_row()
 | 
			
		||||
        index = selected_row.get_index()
 | 
			
		||||
 | 
			
		||||
        if direction == 'next':
 | 
			
		||||
            index += 1
 | 
			
		||||
        else:
 | 
			
		||||
            index -= 1
 | 
			
		||||
 | 
			
		||||
        while True:
 | 
			
		||||
            new_selected_row = self.listbox.get_row_at_index(index)
 | 
			
		||||
            if new_selected_row is None:
 | 
			
		||||
                return
 | 
			
		||||
        app.interface.new_chat_from_jid(self.account, jid)
 | 
			
		||||
            if new_selected_row.get_child_visible():
 | 
			
		||||
                self.listbox.select_row(new_selected_row)
 | 
			
		||||
                new_selected_row.grab_focus()
 | 
			
		||||
                return
 | 
			
		||||
            if direction == 'next':
 | 
			
		||||
                index += 1
 | 
			
		||||
            else:
 | 
			
		||||
                index -= 1
 | 
			
		||||
 | 
			
		||||
    def select_first_row(self):
 | 
			
		||||
        first_row = self.listbox.get_row_at_y(0)
 | 
			
		||||
        self.listbox.select_row(first_row)
 | 
			
		||||
 | 
			
		||||
    def _filter_func(self, row, user_data):
 | 
			
		||||
        search_text = self.search_entry.get_text().lower()
 | 
			
		||||
        search_text_list = search_text.split()
 | 
			
		||||
        row_text = row.get_child().get_search_text().lower()
 | 
			
		||||
        for text in search_text_list:
 | 
			
		||||
            if text not in row_text:
 | 
			
		||||
                GLib.timeout_add(50, self.select_first_row)
 | 
			
		||||
                return
 | 
			
		||||
        GLib.timeout_add(50, self.select_first_row)
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def _sort_func(row1, row2, user_data):
 | 
			
		||||
        name1 = row1.get_child().get_search_text()
 | 
			
		||||
        name2 = row2.get_child().get_search_text()
 | 
			
		||||
        account1 = row1.get_child().account
 | 
			
		||||
        account2 = row2.get_child().account
 | 
			
		||||
        is_groupchat1 = row1.get_child().groupchat
 | 
			
		||||
        is_groupchat2 = row2.get_child().groupchat
 | 
			
		||||
        new1 = row1.get_child().new
 | 
			
		||||
        new2 = row2.get_child().new
 | 
			
		||||
 | 
			
		||||
        result = locale.strcoll(account1.lower(), account2.lower())
 | 
			
		||||
        if result != 0:
 | 
			
		||||
            return result
 | 
			
		||||
 | 
			
		||||
        if new1 != new2:
 | 
			
		||||
            return 1 if new1 else -1
 | 
			
		||||
 | 
			
		||||
        if is_groupchat1 != is_groupchat2:
 | 
			
		||||
            return 1 if is_groupchat1 else -1
 | 
			
		||||
 | 
			
		||||
        return locale.strcoll(name1.lower(), name2.lower())
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def _destroy(*args):
 | 
			
		||||
        del app.interface.instances['start_chat']
 | 
			
		||||
 | 
			
		||||
class ContactRow(Gtk.Grid):
 | 
			
		||||
    def __init__(self, account, contact, jid, name, show_account,
 | 
			
		||||
                 groupchat=False):
 | 
			
		||||
        Gtk.Grid.__init__(self)
 | 
			
		||||
        self.set_column_spacing(12)
 | 
			
		||||
        self.set_size_request(260, -1)
 | 
			
		||||
        self.account = account
 | 
			
		||||
        self.account_label = app.config.get_per(
 | 
			
		||||
            'accounts', account, 'account_label') or account
 | 
			
		||||
        self.show_account = show_account
 | 
			
		||||
        self.jid = jid
 | 
			
		||||
        self.contact = contact
 | 
			
		||||
        self.name = name
 | 
			
		||||
        self.groupchat = groupchat
 | 
			
		||||
        self.new = jid == ''
 | 
			
		||||
 | 
			
		||||
        if self.groupchat:
 | 
			
		||||
            if self.new:
 | 
			
		||||
                muc_image = app.interface.jabber_state_images['32']['muc_inactive']
 | 
			
		||||
            else:
 | 
			
		||||
                muc_image = app.interface.jabber_state_images['32']['muc_active']
 | 
			
		||||
            image = Gtk.Image.new_from_pixbuf(muc_image.get_pixbuf())
 | 
			
		||||
        else:
 | 
			
		||||
            avatar = app.contacts.get_avatar(account, jid, AvatarSize.ROSTER)
 | 
			
		||||
            if avatar is None:
 | 
			
		||||
                image = Gtk.Image.new_from_icon_name(
 | 
			
		||||
                    'avatar-default', Gtk.IconSize.DND)
 | 
			
		||||
            else:
 | 
			
		||||
                image = Gtk.Image.new_from_pixbuf(avatar)
 | 
			
		||||
        self.add(image)
 | 
			
		||||
 | 
			
		||||
        middle_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0)
 | 
			
		||||
        middle_box.set_hexpand(True)
 | 
			
		||||
 | 
			
		||||
        if self.name is None:
 | 
			
		||||
            if self.groupchat:
 | 
			
		||||
                self.name = _('New Groupchat')
 | 
			
		||||
            else:
 | 
			
		||||
                self.name = _('New Contact')
 | 
			
		||||
 | 
			
		||||
        self.name_label = Gtk.Label(self.name)
 | 
			
		||||
        self.name_label.set_halign(Gtk.Align.START)
 | 
			
		||||
        self.name_label.get_style_context().add_class('bold16')
 | 
			
		||||
 | 
			
		||||
        status = contact.show if contact else 'offline'
 | 
			
		||||
        css_class = helpers.get_css_show_color(status)
 | 
			
		||||
        if css_class is not None:
 | 
			
		||||
            self.name_label.get_style_context().add_class(css_class)
 | 
			
		||||
        middle_box.add(self.name_label)
 | 
			
		||||
 | 
			
		||||
        self.jid_label = Gtk.Label(jid)
 | 
			
		||||
        self.jid_label.set_halign(Gtk.Align.START)
 | 
			
		||||
        middle_box.add(self.jid_label)
 | 
			
		||||
 | 
			
		||||
        self.add(middle_box)
 | 
			
		||||
 | 
			
		||||
        if show_account:
 | 
			
		||||
            account_label = Gtk.Label(self.account_label)
 | 
			
		||||
            account_label.set_halign(Gtk.Align.START)
 | 
			
		||||
            account_label.set_valign(Gtk.Align.START)
 | 
			
		||||
 | 
			
		||||
            right_box = Gtk.Box()
 | 
			
		||||
            right_box.set_vexpand(True)
 | 
			
		||||
            right_box.add(account_label)
 | 
			
		||||
            self.add(right_box)
 | 
			
		||||
 | 
			
		||||
        self.show_all()
 | 
			
		||||
 | 
			
		||||
    def update_jid(self, jid):
 | 
			
		||||
        self.jid = jid
 | 
			
		||||
        self.jid_label.set_text(jid)
 | 
			
		||||
 | 
			
		||||
    def get_search_text(self):
 | 
			
		||||
        if self.contact is None and not self.groupchat:
 | 
			
		||||
            return self.jid
 | 
			
		||||
        if self.show_account:
 | 
			
		||||
            return '%s %s %s' % (self.name, self.jid, self.account_label)
 | 
			
		||||
        return '%s %s' % (self.name, self.jid)
 | 
			
		||||
 | 
			
		||||
class ChangePasswordDialog:
 | 
			
		||||
    def __init__(self, account, on_response, transient_for=None):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -307,7 +307,6 @@ class GajimApplication(Gtk.Application):
 | 
			
		|||
 | 
			
		||||
        self.account_actions = [
 | 
			
		||||
            ('-start-single-chat', action.on_single_message, 'online', 's'),
 | 
			
		||||
            ('-start-chat', action.on_new_chat, 'online', 's'),
 | 
			
		||||
            ('-join-groupchat', action.on_join_gc, 'online', 's'),
 | 
			
		||||
            ('-add-contact', action.on_add_contact, 'online', 's'),
 | 
			
		||||
            ('-services', action.on_service_disco, 'online', 's'),
 | 
			
		||||
| 
						 | 
				
			
			@ -348,6 +347,7 @@ class GajimApplication(Gtk.Application):
 | 
			
		|||
            ('accounts', action.on_accounts),
 | 
			
		||||
            ('add-account', action.on_add_account),
 | 
			
		||||
            ('manage-proxies', action.on_manage_proxies),
 | 
			
		||||
            ('start-chat', action.on_new_chat),
 | 
			
		||||
            ('bookmarks', action.on_manage_bookmarks),
 | 
			
		||||
            ('history-manager', action.on_history_manager),
 | 
			
		||||
            ('preferences', action.on_preferences),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -722,7 +722,6 @@ def get_account_menu(account):
 | 
			
		|||
            ('-join-groupchat', _('Join Group Chat')),
 | 
			
		||||
            ('-profile', _('Profile')),
 | 
			
		||||
            ('-services', _('Discover Services')),
 | 
			
		||||
            ('-start-chat', _('Start Chat...')),
 | 
			
		||||
            ('-start-single-chat', _('Send Single Message...')),
 | 
			
		||||
            ('Advanced', [
 | 
			
		||||
                ('-archive', _('Archiving Preferences')),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,7 +35,7 @@ import mimetypes
 | 
			
		|||
from gajim.common import app
 | 
			
		||||
from gajim.common import helpers
 | 
			
		||||
from time import time
 | 
			
		||||
from gajim.dialogs import AddNewContactWindow, NewChatDialog, JoinGroupchatWindow
 | 
			
		||||
from gajim.dialogs import AddNewContactWindow, JoinGroupchatWindow
 | 
			
		||||
from gajim.common import ged
 | 
			
		||||
from gajim.common.connection_handlers_events import MessageOutgoingEvent
 | 
			
		||||
from gajim.common.connection_handlers_events import GcMessageOutgoingEvent
 | 
			
		||||
| 
						 | 
				
			
			@ -849,7 +849,7 @@ class SignalObject(dbus.service.Object):
 | 
			
		|||
        if not account:
 | 
			
		||||
            # error is shown in gajim-remote check_arguments(..)
 | 
			
		||||
            return DBUS_BOOLEAN(False)
 | 
			
		||||
        NewChatDialog(account)
 | 
			
		||||
        app.app.activate_action('start-chat')
 | 
			
		||||
        return DBUS_BOOLEAN(True)
 | 
			
		||||
 | 
			
		||||
    @dbus.service.method(INTERFACE, in_signature='ss', out_signature='')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3677,9 +3677,6 @@ class RosterWindow:
 | 
			
		|||
            app.interface.instances[account]['join_gc'] = \
 | 
			
		||||
                    dialogs.JoinGroupchatWindow(account, None)
 | 
			
		||||
 | 
			
		||||
    def on_new_chat_menuitem_activate(self, widget, account):
 | 
			
		||||
        dialogs.NewChatDialog(account)
 | 
			
		||||
 | 
			
		||||
    def on_show_transports_action(self, action, param):
 | 
			
		||||
        app.config.set('show_transports_group', param.get_boolean())
 | 
			
		||||
        action.set_state(param)
 | 
			
		||||
| 
						 | 
				
			
			@ -4927,7 +4924,6 @@ class RosterWindow:
 | 
			
		|||
            account_context_menu = xml.get_object('account_context_menu')
 | 
			
		||||
 | 
			
		||||
            status_menuitem = xml.get_object('status_menuitem')
 | 
			
		||||
            start_chat_menuitem = xml.get_object('start_chat_menuitem')
 | 
			
		||||
            join_group_chat_menuitem = xml.get_object(
 | 
			
		||||
                'join_group_chat_menuitem')
 | 
			
		||||
            add_contact_menuitem = xml.get_object('add_contact_menuitem')
 | 
			
		||||
| 
						 | 
				
			
			@ -5015,9 +5011,6 @@ class RosterWindow:
 | 
			
		|||
            execute_command_menuitem.connect('activate',
 | 
			
		||||
                self.on_execute_command, contact, account)
 | 
			
		||||
 | 
			
		||||
            start_chat_menuitem.connect('activate',
 | 
			
		||||
                self.on_new_chat_menuitem_activate, account)
 | 
			
		||||
 | 
			
		||||
            gc_sub_menu = Gtk.Menu() # gc is always a submenu
 | 
			
		||||
            join_group_chat_menuitem.set_submenu(gc_sub_menu)
 | 
			
		||||
            self.add_bookmarks_list(gc_sub_menu, account)
 | 
			
		||||
| 
						 | 
				
			
			@ -5026,7 +5019,7 @@ class RosterWindow:
 | 
			
		|||
            if app.connections[account].connected < 2:
 | 
			
		||||
                for widget in (add_contact_menuitem, service_discovery_menuitem,
 | 
			
		||||
                join_group_chat_menuitem, execute_command_menuitem,
 | 
			
		||||
                pep_menuitem, start_chat_menuitem):
 | 
			
		||||
                pep_menuitem):
 | 
			
		||||
                    widget.set_sensitive(False)
 | 
			
		||||
        else:
 | 
			
		||||
            xml = gtkgui_helpers.get_gtk_builder('zeroconf_context_menu.ui')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -185,7 +185,7 @@ class StatusIcon:
 | 
			
		|||
        dialogs.SingleMessageWindow(account, action='send')
 | 
			
		||||
 | 
			
		||||
    def on_new_chat(self, widget, account):
 | 
			
		||||
        dialogs.NewChatDialog(account)
 | 
			
		||||
        app.app.activate_action('start-chat')
 | 
			
		||||
 | 
			
		||||
    def make_menu(self, event_button, event_time):
 | 
			
		||||
        """
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -628,7 +628,7 @@ if dbus_support.supported:
 | 
			
		|||
                if not account:
 | 
			
		||||
                    # error is shown in gajim-remote check_arguments(..)
 | 
			
		||||
                    return DBUS_BOOLEAN(False)
 | 
			
		||||
                NewChatDialog(account)
 | 
			
		||||
                app.app.activate_action('start-chat')
 | 
			
		||||
                return DBUS_BOOLEAN(True)
 | 
			
		||||
 | 
			
		||||
            @dbus.service.method(INTERFACE, in_signature='ss', out_signature='')
 | 
			
		||||
| 
						 | 
				
			
			@ -658,7 +658,7 @@ if dbus_support.supported:
 | 
			
		|||
from gajim.common import app
 | 
			
		||||
from gajim.common import helpers
 | 
			
		||||
from time import time
 | 
			
		||||
from gajim.dialogs import AddNewContactWindow, NewChatDialog, JoinGroupchatWindow
 | 
			
		||||
from gajim.dialogs import AddNewContactWindow, JoinGroupchatWindow
 | 
			
		||||
 | 
			
		||||
from gajim.plugins import GajimPlugin
 | 
			
		||||
from gajim.plugins.helpers import log_calls, log
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue