Merge branch 'master' into 'master'
New JoinGroupchat/StartChat Dialog See merge request gajim/gajim!161
This commit is contained in:
commit
1ebcbac58a
28 changed files with 1128 additions and 852 deletions
|
@ -19,8 +19,6 @@ by D-Bus.
|
||||||
.El
|
.El
|
||||||
.Ss account_info Aq account
|
.Ss account_info Aq account
|
||||||
Gets detailed info on a account
|
Gets detailed info on a account
|
||||||
.Ss add_contact Ao jid Ac Bq account
|
|
||||||
Adds contact to roster
|
|
||||||
.Ss change_avatar Ao picture Ac Bq account
|
.Ss change_avatar Ao picture Ac Bq account
|
||||||
Change the avatar
|
Change the avatar
|
||||||
.Ss change_status Bo status Bc Bo message Bc Bq account
|
.Ss change_status Bo status Bc Bo message Bc Bq account
|
||||||
|
@ -35,18 +33,12 @@ Returns current status (the global one unless account is specified)
|
||||||
Returns current status message (the global one unless account is specified)
|
Returns current status message (the global one unless account is specified)
|
||||||
.Ss get_unread_msgs_number
|
.Ss get_unread_msgs_number
|
||||||
Returns number of unread messages
|
Returns number of unread messages
|
||||||
.Ss handle_uri Ao uri Ac Bo account Bc Bq message
|
|
||||||
Handle a xmpp:/ uri
|
|
||||||
.Ss help Bq command
|
.Ss help Bq command
|
||||||
Shows a help on specific command
|
Shows a help on specific command
|
||||||
.Ss join_room Ao room Ac Bo nick Bc Bo password Bc Bq account
|
|
||||||
Join a MUC room
|
|
||||||
.Ss list_accounts
|
.Ss list_accounts
|
||||||
Prints a list of registered accounts
|
Prints a list of registered accounts
|
||||||
.Ss list_contacts Bq account
|
.Ss list_contacts Bq account
|
||||||
Prints a list of all contacts in the roster. Each contact appears on a separate line
|
Prints a list of all contacts in the roster. Each contact appears on a separate line
|
||||||
.Ss open_chat Ao jid Ac Bo account Bc Bq message
|
|
||||||
Shows the chat dialog so that you can send messages to a contact
|
|
||||||
.Ss prefs_del Aq key
|
.Ss prefs_del Aq key
|
||||||
Deletes a preference item
|
Deletes a preference item
|
||||||
.Ss prefs_list
|
.Ss prefs_list
|
||||||
|
@ -71,8 +63,6 @@ Sends custom XML
|
||||||
Changes the priority of account or accounts
|
Changes the priority of account or accounts
|
||||||
.Ss show_next_pending_event
|
.Ss show_next_pending_event
|
||||||
Pops up a window with the next pending event
|
Pops up a window with the next pending event
|
||||||
.Ss start_chat Aq account
|
|
||||||
Opens 'Start Chat' dialog
|
|
||||||
.Ss toggle_ipython
|
.Ss toggle_ipython
|
||||||
Shows or hides the ipython window
|
Shows or hides the ipython window
|
||||||
.Ss toggle_roster_appearance
|
.Ss toggle_roster_appearance
|
||||||
|
|
|
@ -9,5 +9,4 @@ TryExec=gajim-remote
|
||||||
StartupNotify=false
|
StartupNotify=false
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Type=Application
|
Type=Application
|
||||||
MimeType=x-scheme-handler/xmpp;
|
|
||||||
NoDisplay=true
|
NoDisplay=true
|
||||||
|
|
|
@ -13,3 +13,4 @@ StartupNotify=true
|
||||||
StartupWMClass=Gajim
|
StartupWMClass=Gajim
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Type=Application
|
Type=Application
|
||||||
|
MimeType=x-scheme-handler/xmpp;
|
||||||
|
|
|
@ -18,14 +18,15 @@
|
||||||
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
||||||
##
|
##
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
from gajim.common import app
|
from gajim.common import app
|
||||||
from gajim.common import helpers
|
from gajim.common import helpers
|
||||||
from gajim.common.app import interface
|
from gajim.common.app import interface
|
||||||
from gajim.common.exceptions import GajimGeneralException
|
from gajim.common.exceptions import GajimGeneralException
|
||||||
from gi.repository import Gtk
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
|
|
||||||
from gajim import config
|
from gajim import config
|
||||||
from gajim import dialogs
|
from gajim import dialogs
|
||||||
from gajim import features_window
|
from gajim import features_window
|
||||||
|
@ -43,6 +44,11 @@ class AppActions():
|
||||||
def __init__(self, application: Gtk.Application):
|
def __init__(self, application: Gtk.Application):
|
||||||
self.application = application
|
self.application = application
|
||||||
|
|
||||||
|
# General Actions
|
||||||
|
|
||||||
|
def on_add_contact_jid(self, action, param):
|
||||||
|
dialogs.AddNewContactWindow(None, param.get_string())
|
||||||
|
|
||||||
# Application Menu Actions
|
# Application Menu Actions
|
||||||
|
|
||||||
def on_preferences(self, action, param):
|
def on_preferences(self, action, param):
|
||||||
|
@ -74,6 +80,12 @@ class AppActions():
|
||||||
def on_quit(self, action, param):
|
def on_quit(self, action, param):
|
||||||
interface.roster.on_quit_request()
|
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
|
# Accounts Actions
|
||||||
|
|
||||||
def on_profile(self, action, param):
|
def on_profile(self, action, param):
|
||||||
|
@ -116,20 +128,14 @@ class AppActions():
|
||||||
'You cannot join a group chat while you are invisible'))
|
'You cannot join a group chat while you are invisible'))
|
||||||
return
|
return
|
||||||
if 'join_gc' in interface.instances[account]:
|
if 'join_gc' in interface.instances[account]:
|
||||||
interface.instances[account]['join_gc'].window.present()
|
interface.instances[account]['join_gc'].present()
|
||||||
else:
|
else:
|
||||||
try:
|
|
||||||
interface.instances[account]['join_gc'] = \
|
interface.instances[account]['join_gc'] = \
|
||||||
dialogs.JoinGroupchatWindow(account)
|
dialogs.JoinGroupchatWindow(account, None)
|
||||||
except GajimGeneralException:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def on_add_contact(self, action, param):
|
def on_add_contact(self, action, param):
|
||||||
dialogs.AddNewContactWindow(param.get_string())
|
dialogs.AddNewContactWindow(param.get_string())
|
||||||
|
|
||||||
def on_new_chat(self, action, param):
|
|
||||||
dialogs.NewChatDialog(param.get_string())
|
|
||||||
|
|
||||||
def on_single_message(self, action, param):
|
def on_single_message(self, action, param):
|
||||||
dialogs.SingleMessageWindow(param.get_string(), action='send')
|
dialogs.SingleMessageWindow(param.get_string(), action='send')
|
||||||
|
|
||||||
|
|
|
@ -1601,15 +1601,13 @@ class ChatControl(ChatControlBase):
|
||||||
self._add_info_bar_message(markup, [b], file_props, Gtk.MessageType.ERROR)
|
self._add_info_bar_message(markup, [b], file_props, Gtk.MessageType.ERROR)
|
||||||
|
|
||||||
def _on_accept_gc_invitation(self, widget, event):
|
def _on_accept_gc_invitation(self, widget, event):
|
||||||
try:
|
|
||||||
if event.is_continued:
|
if event.is_continued:
|
||||||
app.interface.join_gc_room(self.account, event.room_jid,
|
app.interface.join_gc_room(self.account, event.room_jid,
|
||||||
app.nicks[self.account], event.password,
|
app.nicks[self.account], event.password,
|
||||||
is_continued=True)
|
is_continued=True)
|
||||||
else:
|
else:
|
||||||
dialogs.JoinGroupchatWindow(self.account, event.room_jid)
|
app.interface.join_gc_minimal(self.account, event.room_jid)
|
||||||
except GajimGeneralException:
|
|
||||||
pass
|
|
||||||
app.events.remove_events(self.account, self.contact.jid, event=event)
|
app.events.remove_events(self.account, self.contact.jid, event=event)
|
||||||
|
|
||||||
def _on_cancel_gc_invitation(self, widget, event):
|
def _on_cancel_gc_invitation(self, widget, event):
|
||||||
|
|
|
@ -296,21 +296,12 @@ class StandardGroupChatCommands(CommandContainer):
|
||||||
'room_jid': self.room_jid}
|
'room_jid': self.room_jid}
|
||||||
|
|
||||||
@command(raw=True, empty=True)
|
@command(raw=True, empty=True)
|
||||||
@doc(_("Join a group chat given by a jid, optionally using given nickname"))
|
@doc(_("Join a group chat given by a jid"))
|
||||||
def join(self, jid, nick):
|
def join(self, jid):
|
||||||
if not nick:
|
|
||||||
nick = self.nick
|
|
||||||
|
|
||||||
if '@' not in jid:
|
if '@' not in jid:
|
||||||
jid = jid + '@' + app.get_server_from_jid(self.room_jid)
|
jid = jid + '@' + app.get_server_from_jid(self.room_jid)
|
||||||
|
|
||||||
try:
|
app.interface.join_gc_minimal(self.account, room_jid=jid)
|
||||||
app.interface.instances[self.account]['join_gc'].window.present()
|
|
||||||
except KeyError:
|
|
||||||
try:
|
|
||||||
dialogs.JoinGroupchatWindow(account=self.account, room_jid=jid, nick=nick)
|
|
||||||
except GajimGeneralException:
|
|
||||||
pass
|
|
||||||
|
|
||||||
@command('part', 'close', raw=True, empty=True)
|
@command('part', 'close', raw=True, empty=True)
|
||||||
@doc(_("Leave the groupchat, optionally giving a reason, and close tab or window"))
|
@doc(_("Leave the groupchat, optionally giving a reason, and close tab or window"))
|
||||||
|
|
|
@ -33,6 +33,7 @@ import logging
|
||||||
import locale
|
import locale
|
||||||
import uuid
|
import uuid
|
||||||
from distutils.version import LooseVersion as V
|
from distutils.version import LooseVersion as V
|
||||||
|
from collections import namedtuple
|
||||||
import gi
|
import gi
|
||||||
import nbxmpp
|
import nbxmpp
|
||||||
import hashlib
|
import hashlib
|
||||||
|
@ -81,6 +82,8 @@ PLUGINS_DIRS = [gajimpaths['PLUGINS_BASE'],
|
||||||
PLUGINS_CONFIG_DIR = gajimpaths['PLUGINS_CONFIG_DIR']
|
PLUGINS_CONFIG_DIR = gajimpaths['PLUGINS_CONFIG_DIR']
|
||||||
MY_CERT_DIR = gajimpaths['MY_CERT']
|
MY_CERT_DIR = gajimpaths['MY_CERT']
|
||||||
|
|
||||||
|
RecentGroupchat = namedtuple('RecentGroupchat', ['room', 'server', 'nickname'])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
LANG = locale.getdefaultlocale()[0] # en_US, fr_FR, el_GR etc..
|
LANG = locale.getdefaultlocale()[0] # en_US, fr_FR, el_GR etc..
|
||||||
except (ValueError, locale.Error):
|
except (ValueError, locale.Error):
|
||||||
|
@ -373,6 +376,16 @@ def get_number_of_connected_accounts(accounts_list = None):
|
||||||
connected_accounts = connected_accounts + 1
|
connected_accounts = connected_accounts + 1
|
||||||
return connected_accounts
|
return connected_accounts
|
||||||
|
|
||||||
|
def get_connected_accounts():
|
||||||
|
"""
|
||||||
|
Returns a list of CONNECTED accounts
|
||||||
|
"""
|
||||||
|
account_list = []
|
||||||
|
for account in connections:
|
||||||
|
if account_is_connected(account):
|
||||||
|
account_list.append(account)
|
||||||
|
return account_list
|
||||||
|
|
||||||
def account_is_connected(account):
|
def account_is_connected(account):
|
||||||
if account not in connections:
|
if account not in connections:
|
||||||
return False
|
return False
|
||||||
|
@ -388,6 +401,11 @@ def zeroconf_is_connected():
|
||||||
return account_is_connected(ZEROCONF_ACC_NAME) and \
|
return account_is_connected(ZEROCONF_ACC_NAME) and \
|
||||||
config.get_per('accounts', ZEROCONF_ACC_NAME, 'is_zeroconf')
|
config.get_per('accounts', ZEROCONF_ACC_NAME, 'is_zeroconf')
|
||||||
|
|
||||||
|
def in_groupchat(account, room_jid):
|
||||||
|
if room_jid not in gc_connected[account]:
|
||||||
|
return False
|
||||||
|
return gc_connected[account][room_jid]
|
||||||
|
|
||||||
def get_number_of_securely_connected_accounts():
|
def get_number_of_securely_connected_accounts():
|
||||||
"""
|
"""
|
||||||
Return the number of the accounts that are SSL/TLS connected
|
Return the number of the accounts that are SSL/TLS connected
|
||||||
|
@ -495,6 +513,34 @@ def get_name_from_jid(account, jid):
|
||||||
actor = jid
|
actor = jid
|
||||||
return actor
|
return actor
|
||||||
|
|
||||||
|
def get_muc_domain(account):
|
||||||
|
return connections[account].muc_jid.get('jabber', None)
|
||||||
|
|
||||||
|
def get_recent_groupchats(account):
|
||||||
|
recent_groupchats = config.get_per(
|
||||||
|
'accounts', account, 'recent_groupchats').split()
|
||||||
|
|
||||||
|
recent_list = []
|
||||||
|
for groupchat in recent_groupchats:
|
||||||
|
jid = nbxmpp.JID(groupchat)
|
||||||
|
recent = RecentGroupchat(
|
||||||
|
jid.getNode(), jid.getDomain(), jid.getResource())
|
||||||
|
recent_list.append(recent)
|
||||||
|
return recent_list
|
||||||
|
|
||||||
|
def add_recent_groupchat(account, room_jid, nickname):
|
||||||
|
recent = config.get_per(
|
||||||
|
'accounts', account, 'recent_groupchats').split()
|
||||||
|
full_jid = room_jid + '/' + nickname
|
||||||
|
if full_jid in recent:
|
||||||
|
recent.remove(full_jid)
|
||||||
|
recent.insert(0, full_jid)
|
||||||
|
if len(recent) > 10:
|
||||||
|
recent = recent[0:9]
|
||||||
|
config_value = ' '.join(recent)
|
||||||
|
config.set_per(
|
||||||
|
'accounts', account, 'recent_groupchats', config_value)
|
||||||
|
|
||||||
def get_priority(account, show):
|
def get_priority(account, show):
|
||||||
"""
|
"""
|
||||||
Return the priority an account must have
|
Return the priority an account must have
|
||||||
|
|
|
@ -472,6 +472,10 @@ class MucCapsCache:
|
||||||
if child.getNamespace() == nbxmpp.NS_DATA:
|
if child.getNamespace() == nbxmpp.NS_DATA:
|
||||||
data.append(nbxmpp.DataForm(node=child))
|
data.append(nbxmpp.DataForm(node=child))
|
||||||
|
|
||||||
|
if nbxmpp.NS_MUC not in features:
|
||||||
|
# Not a MUC, dont cache info
|
||||||
|
return
|
||||||
|
|
||||||
self.cache[jid] = self.DiscoInfo(identities, features, data)
|
self.cache[jid] = self.DiscoInfo(identities, features, data)
|
||||||
|
|
||||||
def is_cached(self, jid):
|
def is_cached(self, jid):
|
||||||
|
|
|
@ -174,7 +174,6 @@ class Config:
|
||||||
'history_window_x-position': [ opt_int, 0 ],
|
'history_window_x-position': [ opt_int, 0 ],
|
||||||
'history_window_y-position': [ opt_int, 0 ],
|
'history_window_y-position': [ opt_int, 0 ],
|
||||||
'latest_disco_addresses': [ opt_str, '' ],
|
'latest_disco_addresses': [ opt_str, '' ],
|
||||||
'recently_groupchat': [ opt_str, '' ],
|
|
||||||
'time_stamp': [ opt_str, '[%X] ', _('This option let you customize timestamp that is printed in conversation. For exemple "[%H:%M] " will show "[hour:minute] ". See python doc on strftime for full documentation: http://docs.python.org/lib/module-time.html') ],
|
'time_stamp': [ opt_str, '[%X] ', _('This option let you customize timestamp that is printed in conversation. For exemple "[%H:%M] " will show "[hour:minute] ". See python doc on strftime for full documentation: http://docs.python.org/lib/module-time.html') ],
|
||||||
'before_nickname': [ opt_str, '', _('Characters that are printed before the nickname in conversations') ],
|
'before_nickname': [ opt_str, '', _('Characters that are printed before the nickname in conversations') ],
|
||||||
'after_nickname': [ opt_str, ':', _('Characters that are printed after the nickname in conversations') ],
|
'after_nickname': [ opt_str, ':', _('Characters that are printed after the nickname in conversations') ],
|
||||||
|
@ -409,6 +408,7 @@ class Config:
|
||||||
'oauth2_client_id': [ opt_str, '0000000044077801', _('client_id for OAuth 2.0 authentication.')],
|
'oauth2_client_id': [ opt_str, '0000000044077801', _('client_id for OAuth 2.0 authentication.')],
|
||||||
'oauth2_redirect_url': [ opt_str, 'https%3A%2F%2Fgajim.org%2Fmsnauth%2Findex.cgi', _('redirect_url for OAuth 2.0 authentication.')],
|
'oauth2_redirect_url': [ opt_str, 'https%3A%2F%2Fgajim.org%2Fmsnauth%2Findex.cgi', _('redirect_url for OAuth 2.0 authentication.')],
|
||||||
'opened_chat_controls': [opt_str, '', _('Space separated list of JIDs for which we want to re-open a chat window on next startup.')],
|
'opened_chat_controls': [opt_str, '', _('Space separated list of JIDs for which we want to re-open a chat window on next startup.')],
|
||||||
|
'recent_groupchats': [ opt_str, '' ],
|
||||||
}, {}),
|
}, {}),
|
||||||
'statusmsg': ({
|
'statusmsg': ({
|
||||||
'message': [ opt_str, '' ],
|
'message': [ opt_str, '' ],
|
||||||
|
|
|
@ -98,6 +98,9 @@ class ConnectionDisco:
|
||||||
self.disco_info_ids.append(id_)
|
self.disco_info_ids.append(id_)
|
||||||
|
|
||||||
def discoverMUC(self, jid, callback):
|
def discoverMUC(self, jid, callback):
|
||||||
|
if muc_caps_cache.is_cached(jid):
|
||||||
|
callback()
|
||||||
|
return
|
||||||
disco_info = nbxmpp.Iq(typ='get', to=jid, queryNS=nbxmpp.NS_DISCO_INFO)
|
disco_info = nbxmpp.Iq(typ='get', to=jid, queryNS=nbxmpp.NS_DISCO_INFO)
|
||||||
self.connection.SendAndCallForResponse(
|
self.connection.SendAndCallForResponse(
|
||||||
disco_info, self.received_muc_info, {'callback': callback})
|
disco_info, self.received_muc_info, {'callback': callback})
|
||||||
|
|
|
@ -411,6 +411,16 @@ def get_uf_show(show, use_mnemonic = False):
|
||||||
uf_show = Q_('?contact has status:Has errors')
|
uf_show = Q_('?contact has status:Has errors')
|
||||||
return uf_show
|
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):
|
def get_uf_sub(sub):
|
||||||
if sub == 'none':
|
if sub == 'none':
|
||||||
uf_sub = Q_('?Subscription we already have:None')
|
uf_sub = Q_('?Subscription we already have:None')
|
||||||
|
|
|
@ -689,15 +689,9 @@ class ConversationTextview(GObject.GObject):
|
||||||
app.interface.new_chat_from_jid(self.account, jid)
|
app.interface.new_chat_from_jid(self.account, jid)
|
||||||
|
|
||||||
def on_join_group_chat_menuitem_activate(self, widget, room_jid):
|
def on_join_group_chat_menuitem_activate(self, widget, room_jid):
|
||||||
if 'join_gc' in app.interface.instances[self.account]:
|
# Remove ?join
|
||||||
instance = app.interface.instances[self.account]['join_gc']
|
room_jid = room_jid.split('?')[0]
|
||||||
instance.xml.get_object('room_jid_entry').set_text(room_jid)
|
app.interface.join_gc_minimal(self.account, room_jid)
|
||||||
app.interface.instances[self.account]['join_gc'].window.present()
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
dialogs.JoinGroupchatWindow(account=self.account, room_jid=room_jid)
|
|
||||||
except GajimGeneralException:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def on_add_to_roster_activate(self, widget, jid):
|
def on_add_to_roster_activate(self, widget, jid):
|
||||||
dialogs.AddNewContactWindow(self.account, jid)
|
dialogs.AddNewContactWindow(self.account, jid)
|
||||||
|
@ -805,7 +799,7 @@ class ConversationTextview(GObject.GObject):
|
||||||
if '?' in word:
|
if '?' in word:
|
||||||
(jid, action) = word.split('?')
|
(jid, action) = word.split('?')
|
||||||
if action == 'join':
|
if action == 'join':
|
||||||
self.on_join_group_chat_menuitem_activate(None, jid)
|
app.interface.join_gc_minimal(None, jid)
|
||||||
else:
|
else:
|
||||||
self.on_start_chat_activate(None, jid)
|
self.on_start_chat_activate(None, jid)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -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>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</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>
|
<child>
|
||||||
<object class="GtkMenuItem" id="join_group_chat_menuitem">
|
<object class="GtkMenuItem" id="join_group_chat_menuitem">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
|
|
@ -72,6 +72,11 @@
|
||||||
<attribute name="action">app.accounts</attribute>
|
<attribute name="action">app.accounts</attribute>
|
||||||
<attribute name="accel"><Primary><Shift>A</attribute>
|
<attribute name="accel"><Primary><Shift>A</attribute>
|
||||||
</item>
|
</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>
|
<item>
|
||||||
<attribute name="label" translatable="yes">Bookmarks</attribute>
|
<attribute name="label" translatable="yes">Bookmarks</attribute>
|
||||||
<attribute name="action">app.bookmarks</attribute>
|
<attribute name="action">app.bookmarks</attribute>
|
||||||
|
|
|
@ -1,78 +1,122 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!-- Generated with glade 3.18.3 -->
|
<!-- Generated with glade 3.20.1 -->
|
||||||
<interface>
|
<interface>
|
||||||
<requires lib="gtk+" version="3.12"/>
|
<requires lib="gtk+" version="3.20"/>
|
||||||
<object class="GtkImage" id="image1">
|
<object class="GtkGrid" id="grid">
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="stock">gtk-find</property>
|
|
||||||
</object>
|
|
||||||
<object class="GtkImage" id="image2">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="stock">gtk-apply</property>
|
|
||||||
</object>
|
|
||||||
<object class="GtkWindow" id="join_groupchat_window">
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="border_width">6</property>
|
|
||||||
<property name="title" translatable="yes">Join Group Chat</property>
|
|
||||||
<property name="resizable">False</property>
|
|
||||||
<property name="type_hint">dialog</property>
|
|
||||||
<signal name="destroy" handler="on_join_groupchat_window_destroy" swapped="no"/>
|
|
||||||
<signal name="key-press-event" handler="on_join_groupchat_window_key_press_event" swapped="no"/>
|
|
||||||
<child>
|
|
||||||
<object class="GtkBox" id="box1">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="orientation">vertical</property>
|
|
||||||
<property name="spacing">12</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkGrid" id="grid1">
|
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_left">18</property>
|
||||||
|
<property name="margin_right">18</property>
|
||||||
|
<property name="margin_top">18</property>
|
||||||
|
<property name="margin_bottom">18</property>
|
||||||
<property name="row_spacing">6</property>
|
<property name="row_spacing">6</property>
|
||||||
<property name="column_spacing">12</property>
|
<property name="column_spacing">12</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkEntry" id="room_jid_entry">
|
<object class="GtkLabel" id="jid_label">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="no_show_all">True</property>
|
||||||
|
<property name="halign">center</property>
|
||||||
|
<property name="margin_bottom">12</property>
|
||||||
|
<style>
|
||||||
|
<class name="bold16"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">0</property>
|
||||||
|
<property name="width">3</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkSwitch" id="bookmark_switch">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="activates_default">True</property>
|
<property name="tooltip_text" translatable="yes">Bookmark this Groupchat</property>
|
||||||
<signal name="changed" handler="on_required_entry_changed" swapped="no"/>
|
<property name="halign">start</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="margin_top">6</property>
|
||||||
|
<property name="active">True</property>
|
||||||
|
<signal name="notify::active" handler="_on_bookmark_activate" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">7</property>
|
||||||
|
<property name="width">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkSwitch" id="autojoin_switch">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Join this Groupchat everytime Gajim is started</property>
|
||||||
|
<property name="halign">start</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="active">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">8</property>
|
||||||
|
<property name="width">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="halign">start</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="margin_top">6</property>
|
||||||
|
<property name="label" translatable="yes">Bookmark</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">7</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="halign">start</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<property name="label" translatable="yes">Autojoin</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">8</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkComboBoxText" id="account_combo">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="no_show_all">True</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<signal name="changed" handler="_on_account_combo_changed" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
<property name="width">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="nick_entry">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">1</property>
|
<property name="left_attach">1</property>
|
||||||
<property name="top_attach">3</property>
|
<property name="top_attach">3</property>
|
||||||
|
<property name="width">2</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="account_label">
|
<object class="GtkLabel" id="account_label">
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="no_show_all">True</property>
|
<property name="no_show_all">True</property>
|
||||||
|
<property name="halign">start</property>
|
||||||
<property name="label" translatable="yes">Account</property>
|
<property name="label" translatable="yes">Account</property>
|
||||||
<property name="xalign">0</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">0</property>
|
|
||||||
<property name="top_attach">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkComboBox" id="account_combobox">
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="no_show_all">True</property>
|
|
||||||
<signal name="changed" handler="on_account_combobox_changed" swapped="no"/>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">1</property>
|
|
||||||
<property name="top_attach">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkLabel" id="label225">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="label" translatable="yes">Recently:</property>
|
|
||||||
<property name="xalign">0</property>
|
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">0</property>
|
<property name="left_attach">0</property>
|
||||||
|
@ -80,46 +124,11 @@
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkComboBox" id="recently_combobox">
|
<object class="GtkLabel">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<signal name="changed" handler="on_recently_combobox_changed" swapped="no"/>
|
<property name="halign">start</property>
|
||||||
</object>
|
<property name="label" translatable="yes">Nickname</property>
|
||||||
<packing>
|
|
||||||
<property name="left_attach">1</property>
|
|
||||||
<property name="top_attach">1</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkLabel" id="label142">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="label" translatable="yes">Nickname:</property>
|
|
||||||
<property name="xalign">0</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">0</property>
|
|
||||||
<property name="top_attach">2</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkEntry" id="nickname_entry">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="activates_default">True</property>
|
|
||||||
<signal name="changed" handler="on_required_entry_changed" swapped="no"/>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">1</property>
|
|
||||||
<property name="top_attach">2</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkLabel" id="label143">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="label" translatable="yes">Room:</property>
|
|
||||||
<property name="xalign">0</property>
|
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">0</property>
|
<property name="left_attach">0</property>
|
||||||
|
@ -127,91 +136,44 @@
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="label1">
|
<object class="GtkLabel" id="password_label">
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="label" translatable="yes">Server:</property>
|
<property name="no_show_all">True</property>
|
||||||
<property name="xalign">0</property>
|
<property name="halign">start</property>
|
||||||
|
<property name="label" translatable="yes">Password</property>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">0</property>
|
<property name="left_attach">0</property>
|
||||||
<property name="top_attach">4</property>
|
<property name="top_attach">6</property>
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkLabel" id="label145">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="label" translatable="yes">Password:</property>
|
|
||||||
<property name="xalign">0</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">0</property>
|
|
||||||
<property name="top_attach">5</property>
|
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkEntry" id="password_entry">
|
<object class="GtkEntry" id="password_entry">
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="visibility">False</property>
|
<property name="no_show_all">True</property>
|
||||||
<property name="activates_default">True</property>
|
<property name="input_purpose">password</property>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">1</property>
|
<property name="left_attach">1</property>
|
||||||
<property name="top_attach">5</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkCheckButton" id="bookmark_checkbutton">
|
|
||||||
<property name="label" translatable="yes">_Bookmark this room</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="receives_default">False</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="xalign">0</property>
|
|
||||||
<property name="draw_indicator">True</property>
|
|
||||||
<signal name="toggled" handler="on_bookmark_checkbutton_toggled" swapped="no"/>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">0</property>
|
|
||||||
<property name="top_attach">6</property>
|
<property name="top_attach">6</property>
|
||||||
<property name="width">2</property>
|
<property name="width">2</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkCheckButton" id="auto_join_checkbutton">
|
<object class="GtkButtonBox" id="button_box">
|
||||||
<property name="label" translatable="yes">Join this room _automatically when I connect</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="sensitive">False</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="receives_default">False</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="xalign">0</property>
|
|
||||||
<property name="draw_indicator">True</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">0</property>
|
|
||||||
<property name="top_attach">7</property>
|
|
||||||
<property name="width">2</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkBox" id="box2">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
|
<property name="no_show_all">True</property>
|
||||||
|
<property name="margin_top">18</property>
|
||||||
<property name="spacing">6</property>
|
<property name="spacing">6</property>
|
||||||
|
<property name="layout_style">end</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkComboBoxText" id="server_comboboxtext">
|
<object class="GtkButton">
|
||||||
|
<property name="label">gtk-cancel</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="has_entry">True</property>
|
|
||||||
<child internal-child="entry">
|
|
||||||
<object class="GtkEntry" id="comboboxtext-entry">
|
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<signal name="changed" handler="on_server_entry_changed" swapped="no"/>
|
<property name="receives_default">True</property>
|
||||||
</object>
|
<property name="use_stock">True</property>
|
||||||
</child>
|
<signal name="clicked" handler="_on_cancel_clicked" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">True</property>
|
<property name="expand">True</property>
|
||||||
|
@ -220,83 +182,159 @@
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkButton" id="browse_rooms_button">
|
<object class="GtkButton" id="join_button">
|
||||||
<property name="label" translatable="yes">Bro_wse Rooms</property>
|
<property name="label" translatable="yes">Join</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
|
<property name="can_default">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="image">image1</property>
|
<signal name="clicked" handler="_on_join_clicked" swapped="no"/>
|
||||||
<property name="use_underline">True</property>
|
<style>
|
||||||
<signal name="clicked" handler="on_browse_rooms_button_clicked" swapped="no"/>
|
<class name="suggested-action"/>
|
||||||
|
</style>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">True</property>
|
||||||
<property name="fill">True</property>
|
<property name="fill">True</property>
|
||||||
<property name="pack_type">end</property>
|
|
||||||
<property name="position">1</property>
|
<property name="position">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">1</property>
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">9</property>
|
||||||
|
<property name="width">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="server_label">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="no_show_all">True</property>
|
||||||
|
<property name="halign">start</property>
|
||||||
|
<property name="label" translatable="yes">Server</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">5</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="room_label">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="no_show_all">True</property>
|
||||||
|
<property name="halign">start</property>
|
||||||
|
<property name="label" translatable="yes">Room</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
<property name="top_attach">4</property>
|
<property name="top_attach">4</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="recent_label">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="no_show_all">True</property>
|
||||||
|
<property name="halign">start</property>
|
||||||
|
<property name="label" translatable="yes">Recently</property>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="left_attach">0</property>
|
||||||
<property name="fill">True</property>
|
<property name="top_attach">2</property>
|
||||||
<property name="position">0</property>
|
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkButtonBox" id="buttonbox1">
|
<object class="GtkEntry" id="room_entry">
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="no_show_all">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">4</property>
|
||||||
|
<property name="width">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkComboBoxText" id="recent_combo">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="no_show_all">True</property>
|
||||||
|
<signal name="changed" handler="_on_recent_changed" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
<property name="width">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkComboBoxText" id="server_combo">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="no_show_all">True</property>
|
||||||
|
<property name="has_entry">True</property>
|
||||||
|
<child internal-child="entry">
|
||||||
|
<object class="GtkEntry">
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="caps_lock_warning">False</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">5</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="search_button">
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="no_show_all">True</property>
|
||||||
|
<property name="tooltip_text" translatable="yes">Search the rooms on this server</property>
|
||||||
|
<signal name="clicked" handler="_on_search_clicked" swapped="no"/>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="spacing">12</property>
|
<property name="icon_name">system-search-symbolic</property>
|
||||||
<property name="layout_style">end</property>
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">2</property>
|
||||||
|
<property name="top_attach">5</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkButton" id="cancel_button">
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<object class="GtkHeaderBar" id="headerbar">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="title">Join Groupchat</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton">
|
||||||
<property name="label">gtk-cancel</property>
|
<property name="label">gtk-cancel</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="can_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="receives_default">False</property>
|
|
||||||
<property name="use_stock">True</property>
|
<property name="use_stock">True</property>
|
||||||
<signal name="clicked" handler="on_cancel_button_clicked" swapped="no"/>
|
<signal name="clicked" handler="_on_cancel_clicked" swapped="no"/>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">False</property>
|
|
||||||
<property name="position">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkButton" id="join_button">
|
<object class="GtkButton">
|
||||||
<property name="label" translatable="yes">_Join</property>
|
<property name="label" translatable="yes">Join</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="can_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="has_default">True</property>
|
<signal name="clicked" handler="_on_join_clicked" swapped="no"/>
|
||||||
<property name="receives_default">False</property>
|
<style>
|
||||||
<property name="image">image2</property>
|
<class name="suggested-action"/>
|
||||||
<property name="use_underline">True</property>
|
</style>
|
||||||
<signal name="clicked" handler="on_join_button_clicked" swapped="no"/>
|
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="pack_type">end</property>
|
||||||
<property name="fill">False</property>
|
|
||||||
<property name="position">1</property>
|
<property name="position">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">True</property>
|
|
||||||
<property name="position">1</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</interface>
|
</interface>
|
||||||
|
|
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,4 +86,16 @@ popover#EmoticonPopover flowboxchild { padding-top: 5px; padding-bottom: 5px; }
|
||||||
background-color: @theme_unfocused_bg_color;
|
background-color: @theme_unfocused_bg_color;
|
||||||
color: @theme_text_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;}
|
||||||
|
|
859
gajim/dialogs.py
859
gajim/dialogs.py
|
@ -38,6 +38,7 @@ from gi.repository import GLib
|
||||||
import os
|
import os
|
||||||
import nbxmpp
|
import nbxmpp
|
||||||
import time
|
import time
|
||||||
|
import locale
|
||||||
|
|
||||||
from gajim import gtkgui_helpers
|
from gajim import gtkgui_helpers
|
||||||
from gajim import vcard
|
from gajim import vcard
|
||||||
|
@ -61,6 +62,8 @@ from gajim.common import app
|
||||||
from gajim.common import helpers
|
from gajim.common import helpers
|
||||||
from gajim.common import i18n
|
from gajim.common import i18n
|
||||||
from gajim.common import dataforms
|
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.exceptions import GajimGeneralException
|
||||||
from gajim.common.connection_handlers_events import MessageOutgoingEvent
|
from gajim.common.connection_handlers_events import MessageOutgoingEvent
|
||||||
|
|
||||||
|
@ -2350,199 +2353,233 @@ class SubscriptionRequestWindow:
|
||||||
gtkgui_helpers.popup_emoticons_under_button(menu, widget,
|
gtkgui_helpers.popup_emoticons_under_button(menu, widget,
|
||||||
self.window.get_window())
|
self.window.get_window())
|
||||||
|
|
||||||
|
class JoinGroupchatWindow(Gtk.ApplicationWindow):
|
||||||
|
def __init__(self, account, room_jid, password=None, automatic=None):
|
||||||
|
Gtk.ApplicationWindow.__init__(self)
|
||||||
|
self.set_name('JoinGroupchat')
|
||||||
|
self.set_application(app.app)
|
||||||
|
self.set_show_menubar(False)
|
||||||
|
self.set_resizable(False)
|
||||||
|
self.set_position(Gtk.WindowPosition.CENTER)
|
||||||
|
self.set_title(_('Join Groupchat'))
|
||||||
|
|
||||||
class JoinGroupchatWindow:
|
|
||||||
def __init__(self, account=None, room_jid='', nick='', password='',
|
|
||||||
automatic=False):
|
|
||||||
"""
|
|
||||||
Automatic is a dict like {'invities': []}. If automatic is not empty,
|
|
||||||
this means room must be automaticaly configured and when done, invities
|
|
||||||
must be automatically invited
|
|
||||||
"""
|
|
||||||
self.window_account = None
|
|
||||||
if account:
|
|
||||||
if room_jid != '' and room_jid in app.gc_connected[account] and \
|
|
||||||
app.gc_connected[account][room_jid]:
|
|
||||||
ErrorDialog(_('You are already in group chat %s') % room_jid)
|
|
||||||
raise GajimGeneralException('You are already in this group chat')
|
|
||||||
if nick == '':
|
|
||||||
nick = app.nicks[account]
|
|
||||||
if app.connections[account].connected < 2:
|
|
||||||
ErrorDialog(_('You are not connected to the server'),
|
|
||||||
_('You can not join a group chat unless you are connected.'))
|
|
||||||
raise GajimGeneralException('You must be connected to join a groupchat')
|
|
||||||
self.window_account = account
|
|
||||||
|
|
||||||
self.xml = gtkgui_helpers.get_gtk_builder('join_groupchat_window.ui')
|
|
||||||
|
|
||||||
account_label = self.xml.get_object('account_label')
|
|
||||||
account_combobox = self.xml.get_object('account_combobox')
|
|
||||||
account_label.set_no_show_all(False)
|
|
||||||
account_combobox.set_no_show_all(False)
|
|
||||||
liststore = Gtk.ListStore(str)
|
|
||||||
account_combobox.set_model(liststore)
|
|
||||||
cell = Gtk.CellRendererText()
|
|
||||||
account_combobox.pack_start(cell, True)
|
|
||||||
account_combobox.add_attribute(cell, 'text', 0)
|
|
||||||
account_combobox.set_active(-1)
|
|
||||||
|
|
||||||
# Add accounts, set current as active if it matches 'account'
|
|
||||||
for acct in [a for a in app.connections if \
|
|
||||||
app.account_is_connected(a)]:
|
|
||||||
if app.connections[acct].is_zeroconf:
|
|
||||||
continue
|
|
||||||
liststore.append([acct])
|
|
||||||
if account and account == acct:
|
|
||||||
account_combobox.set_active(liststore.iter_n_children(None)-1)
|
|
||||||
|
|
||||||
self.account = account
|
|
||||||
self.automatic = automatic
|
self.automatic = automatic
|
||||||
self._empty_required_widgets = []
|
self.password = password
|
||||||
|
|
||||||
self.window = self.xml.get_object('join_groupchat_window')
|
|
||||||
self.window.set_transient_for(app.interface.roster.window)
|
|
||||||
self._room_jid_entry = self.xml.get_object('room_jid_entry')
|
|
||||||
self._nickname_entry = self.xml.get_object('nickname_entry')
|
|
||||||
self._password_entry = self.xml.get_object('password_entry')
|
|
||||||
self.server_comboboxtext = self.xml.get_object('server_comboboxtext')
|
|
||||||
|
|
||||||
self._nickname_entry.set_text(nick)
|
|
||||||
if password:
|
|
||||||
self._password_entry.set_text(password)
|
|
||||||
self.xml.connect_signals(self)
|
|
||||||
title = None
|
|
||||||
if account:
|
|
||||||
# now add us to open windows
|
|
||||||
app.interface.instances[account]['join_gc'] = self
|
|
||||||
if len(app.connections) > 1:
|
|
||||||
title = _('Join Group Chat with account %s') % account
|
|
||||||
if title is None:
|
|
||||||
title = _('Join Group Chat')
|
|
||||||
self.window.set_title(title)
|
|
||||||
|
|
||||||
self.browse_button = self.xml.get_object('browse_rooms_button')
|
|
||||||
self.browse_button.set_sensitive(False)
|
|
||||||
|
|
||||||
self.recently_combobox = self.xml.get_object('recently_combobox')
|
|
||||||
liststore = Gtk.ListStore(str, str)
|
|
||||||
self.recently_combobox.set_model(liststore)
|
|
||||||
cell = Gtk.CellRendererText()
|
|
||||||
self.recently_combobox.pack_start(cell, True)
|
|
||||||
self.recently_combobox.add_attribute(cell, 'text', 0)
|
|
||||||
self.recently_groupchat = app.config.get('recently_groupchat').split()
|
|
||||||
|
|
||||||
server_list = []
|
|
||||||
# get the muc server of our server
|
|
||||||
if 'jabber' in app.connections[account].muc_jid:
|
|
||||||
server_list.append(app.connections[account].muc_jid['jabber'])
|
|
||||||
for g in self.recently_groupchat:
|
|
||||||
r_jid = app.get_jid_without_resource(g)
|
|
||||||
nick = app.get_resource_from_jid(g)
|
|
||||||
if nick:
|
|
||||||
show = '%(nick)s on %(room_jid)s' % {'nick': nick,
|
|
||||||
'room_jid': r_jid}
|
|
||||||
else:
|
|
||||||
show = r_jid
|
|
||||||
liststore.append([show, g])
|
|
||||||
server = app.get_server_from_jid(r_jid)
|
|
||||||
if server not in server_list and not server.startswith('irc'):
|
|
||||||
server_list.append(server)
|
|
||||||
|
|
||||||
for s in server_list:
|
|
||||||
self.server_comboboxtext.append_text(s)
|
|
||||||
|
|
||||||
|
|
||||||
self._set_room_jid(room_jid)
|
|
||||||
|
|
||||||
if len(self.recently_groupchat) == 0:
|
|
||||||
self.recently_combobox.set_sensitive(False)
|
|
||||||
elif room_jid == '':
|
|
||||||
self.recently_combobox.set_active(0)
|
|
||||||
self._room_jid_entry.select_region(0, -1)
|
|
||||||
elif room_jid != '':
|
|
||||||
self.xml.get_object('join_button').grab_focus()
|
|
||||||
|
|
||||||
if not self._room_jid_entry.get_text():
|
|
||||||
self._empty_required_widgets.append(self._room_jid_entry)
|
|
||||||
if not self._nickname_entry.get_text():
|
|
||||||
self._empty_required_widgets.append(self._nickname_entry)
|
|
||||||
if len(self._empty_required_widgets):
|
|
||||||
self.xml.get_object('join_button').set_sensitive(False)
|
|
||||||
|
|
||||||
if account and not app.connections[account].private_storage_supported:
|
|
||||||
self.xml.get_object('bookmark_checkbutton').set_sensitive(False)
|
|
||||||
|
|
||||||
self.requested_jid = None
|
self.requested_jid = None
|
||||||
|
self.room_jid = room_jid
|
||||||
|
self.account = account
|
||||||
|
self.minimal_mode = room_jid is not None
|
||||||
|
|
||||||
|
glade_objects = ['grid', 'nick_entry', 'account_combo', 'jid_label',
|
||||||
|
'bookmark_switch', 'autojoin_switch', 'headerbar',
|
||||||
|
'account_label', 'password_entry', 'password_label',
|
||||||
|
'join_button', 'button_box', 'server_label',
|
||||||
|
'server_combo', 'recent_label', 'recent_combo',
|
||||||
|
'room_label', 'room_entry', 'search_button']
|
||||||
|
|
||||||
|
minimal_widgets = ['jid_label']
|
||||||
|
|
||||||
|
extended_widgets = ['server_label', 'server_combo', 'recent_label',
|
||||||
|
'recent_combo', 'room_label', 'room_entry',
|
||||||
|
'search_button']
|
||||||
|
self.builder = gtkgui_helpers.get_gtk_builder(
|
||||||
|
'join_groupchat_window.ui')
|
||||||
|
for obj in glade_objects:
|
||||||
|
setattr(self, obj, self.builder.get_object(obj))
|
||||||
|
|
||||||
|
self.add(self.grid)
|
||||||
|
|
||||||
|
if os.environ.get('GTK_CSD', '1') == '1':
|
||||||
|
self.set_titlebar(self.headerbar)
|
||||||
|
else:
|
||||||
|
self.button_box.show()
|
||||||
|
|
||||||
|
# Show widgets depending on the mode the window is in
|
||||||
|
if self.minimal_mode:
|
||||||
|
for widget in minimal_widgets:
|
||||||
|
getattr(self, widget).show()
|
||||||
|
self.jid_label.set_text(room_jid)
|
||||||
|
else:
|
||||||
|
for widget in extended_widgets:
|
||||||
|
getattr(self, widget).show()
|
||||||
|
self._fill_recent_and_servers(account)
|
||||||
|
|
||||||
|
if account is None:
|
||||||
|
connected_accounts = app.get_connected_accounts()
|
||||||
|
for acc in connected_accounts:
|
||||||
|
self.account_combo.append_text(acc)
|
||||||
|
else:
|
||||||
|
connected_accounts = [account]
|
||||||
|
self.account_combo.append_text(account)
|
||||||
|
|
||||||
|
self.builder.connect_signals(self)
|
||||||
|
self.connect('key-press-event', self._on_key_press_event)
|
||||||
|
self.connect('destroy', self._on_destroy)
|
||||||
|
|
||||||
|
if not self.minimal_mode:
|
||||||
app.ged.register_event_handler('agent-info-received', ged.GUI1,
|
app.ged.register_event_handler('agent-info-received', ged.GUI1,
|
||||||
self._nec_agent_info_received)
|
self._nec_agent_info_received)
|
||||||
app.ged.register_event_handler('agent-info-error-received', ged.GUI1,
|
app.ged.register_event_handler('agent-info-error-received', ged.GUI1,
|
||||||
self._nec_agent_info_error_received)
|
self._nec_agent_info_error_received)
|
||||||
|
|
||||||
self.window.show_all()
|
# Show account combobox if there is more than one account
|
||||||
|
if len(connected_accounts) > 1:
|
||||||
|
self.account_combo.show()
|
||||||
|
self.account_label.show()
|
||||||
|
|
||||||
def on_join_groupchat_window_destroy(self, widget):
|
# Select first account
|
||||||
"""
|
self.account_combo.set_active(0)
|
||||||
Close window
|
if not self.minimal_mode:
|
||||||
"""
|
self.recent_combo.set_active(0)
|
||||||
|
|
||||||
|
if self.password is not None:
|
||||||
|
self.password_entry.set_text(self.password)
|
||||||
|
|
||||||
|
# Set bookmark switch sensitive if server supports bookmarks
|
||||||
|
acc = self.account_combo.get_active_text()
|
||||||
|
if not app.connections[acc].private_storage_supported:
|
||||||
|
self.bookmark_switch.set_sensitive(False)
|
||||||
|
self.autojoin_switch.set_sensitive(False)
|
||||||
|
|
||||||
|
# Show password field if we are in extended mode or
|
||||||
|
# The MUC is passwordprotected
|
||||||
|
if not self.minimal_mode or muc_caps_cache.supports(
|
||||||
|
room_jid, 'muc_passwordprotected'):
|
||||||
|
self.password_entry.show()
|
||||||
|
self.password_label.show()
|
||||||
|
|
||||||
|
self.show_all()
|
||||||
|
|
||||||
|
def set_room(self, room_jid):
|
||||||
|
room, server = app.get_name_and_server_from_jid(room_jid)
|
||||||
|
self.room_entry.set_text(room)
|
||||||
|
self.server_combo.get_child().set_text(server)
|
||||||
|
|
||||||
|
def _fill_recent_and_servers(self, account):
|
||||||
|
recent = app.get_recent_groupchats(account)
|
||||||
|
servers = []
|
||||||
|
for groupchat in recent:
|
||||||
|
text = '%s on %s@%s' % (groupchat.nickname,
|
||||||
|
groupchat.room,
|
||||||
|
groupchat.server)
|
||||||
|
self.recent_combo.append_text(text)
|
||||||
|
servers.append(groupchat.server)
|
||||||
|
|
||||||
|
for server in set(servers):
|
||||||
|
self.server_combo.append_text(server)
|
||||||
|
|
||||||
|
# Add own Server to ComboBox
|
||||||
|
muc_domain = app.get_muc_domain(account)
|
||||||
|
if muc_domain is not None:
|
||||||
|
self.server_combo.insert_text(0, muc_domain)
|
||||||
|
|
||||||
|
def _on_recent_changed(self, combo):
|
||||||
|
text = combo.get_active_text()
|
||||||
|
if text is None:
|
||||||
|
self.server_combo.set_active(0)
|
||||||
|
return
|
||||||
|
nickname, _, room_jid = text.split()
|
||||||
|
room, server = app.get_name_and_server_from_jid(room_jid)
|
||||||
|
self.room_entry.set_text(room)
|
||||||
|
self.nick_entry.set_text(nickname)
|
||||||
|
self.server_combo.get_child().set_text(server)
|
||||||
|
|
||||||
|
def _on_account_combo_changed(self, combo):
|
||||||
|
account = combo.get_active_text()
|
||||||
|
self.nick_entry.set_text(app.nicks[account])
|
||||||
|
|
||||||
|
def _on_key_press_event(self, widget, event):
|
||||||
|
if event.keyval == Gdk.KEY_Escape:
|
||||||
|
self.destroy()
|
||||||
|
if event.keyval == Gdk.KEY_Return:
|
||||||
|
self._on_join_clicked()
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _on_join_clicked(self, *args):
|
||||||
|
account = self.account_combo.get_active_text()
|
||||||
|
nickname = self.nick_entry.get_text()
|
||||||
|
|
||||||
|
if not self.minimal_mode:
|
||||||
|
server = self.server_combo.get_active_text()
|
||||||
|
room = self.room_entry.get_text()
|
||||||
|
if room == '':
|
||||||
|
ErrorDialog(_('Invalid Room'),
|
||||||
|
_('Please choose a room'), transient_for=self)
|
||||||
|
return
|
||||||
|
self.room_jid = '%s@%s' % (room, server)
|
||||||
|
|
||||||
|
if app.in_groupchat(account, self.room_jid):
|
||||||
|
# If we already in the groupchat, join_gc_room will bring
|
||||||
|
# it to front
|
||||||
|
app.interface.join_gc_room(account, self.room_jid, nickname, '')
|
||||||
|
self.destroy()
|
||||||
|
return
|
||||||
|
|
||||||
|
if nickname == '':
|
||||||
|
ErrorDialog(_('Invalid Nickname'),
|
||||||
|
_('Please choose a nickname'), transient_for=self)
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
helpers.parse_resource(nickname)
|
||||||
|
except helpers.InvalidFormat as error:
|
||||||
|
ErrorDialog(_('Invalid Nickname'), str(error), transient_for=self)
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
helpers.parse_jid(self.room_jid)
|
||||||
|
except helpers.InvalidFormat as error:
|
||||||
|
ErrorDialog(_('Invalid JID'), str(error), transient_for=self)
|
||||||
|
return
|
||||||
|
|
||||||
|
if not app.account_is_connected(account):
|
||||||
|
ErrorDialog(
|
||||||
|
_('You are not connected to the server'),
|
||||||
|
_('You can not join a group chat unless you are connected.'),
|
||||||
|
transient_for=self)
|
||||||
|
return
|
||||||
|
|
||||||
|
password = self.password_entry.get_text()
|
||||||
|
self._add_bookmark(account, nickname, password)
|
||||||
|
app.add_recent_groupchat(account, self.room_jid, nickname)
|
||||||
|
|
||||||
|
if self.automatic:
|
||||||
|
app.automatic_rooms[self.account][self.room_jid] = self.automatic
|
||||||
|
|
||||||
|
app.interface.join_gc_room(account, self.room_jid, nickname, password)
|
||||||
|
self.destroy()
|
||||||
|
|
||||||
|
def _on_cancel_clicked(self, *args):
|
||||||
|
self.destroy()
|
||||||
|
|
||||||
|
def _on_bookmark_activate(self, switch, param):
|
||||||
|
self.autojoin_switch.set_sensitive(switch.get_active())
|
||||||
|
|
||||||
|
def _add_bookmark(self, account, nickname, password):
|
||||||
|
if not app.connections[account].private_storage_supported:
|
||||||
|
return
|
||||||
|
|
||||||
|
add_bookmark = self.bookmark_switch.get_active()
|
||||||
|
if not add_bookmark:
|
||||||
|
return
|
||||||
|
|
||||||
|
autojoin = int(self.autojoin_switch.get_active())
|
||||||
|
|
||||||
|
# Add as bookmark, with autojoin and not minimized
|
||||||
|
name = app.get_nick_from_jid(self.room_jid)
|
||||||
|
app.interface.add_gc_bookmark(
|
||||||
|
account, name, self.room_jid, autojoin, 0, password, nickname)
|
||||||
|
|
||||||
|
def _on_destroy(self, *args):
|
||||||
|
if not self.minimal_mode:
|
||||||
|
del app.interface.instances[self.account]['join_gc']
|
||||||
app.ged.remove_event_handler('agent-info-received', ged.GUI1,
|
app.ged.remove_event_handler('agent-info-received', ged.GUI1,
|
||||||
self._nec_agent_info_received)
|
self._nec_agent_info_received)
|
||||||
app.ged.register_event_handler('agent-info-error-received', ged.GUI1,
|
app.ged.remove_event_handler('agent-info-error-received', ged.GUI1,
|
||||||
self._nec_agent_info_error_received)
|
self._nec_agent_info_error_received)
|
||||||
if self.window_account and 'join_gc' in app.interface.instances[
|
|
||||||
self.window_account]:
|
|
||||||
# remove us from open windows
|
|
||||||
del app.interface.instances[self.window_account]['join_gc']
|
|
||||||
|
|
||||||
def on_join_groupchat_window_key_press_event(self, widget, event):
|
def _on_search_clicked(self, widget):
|
||||||
if event.keyval == Gdk.KEY_Escape: # ESCAPE
|
server = self.server_combo.get_active_text()
|
||||||
widget.destroy()
|
|
||||||
|
|
||||||
def on_required_entry_changed(self, widget):
|
|
||||||
if not widget.get_text():
|
|
||||||
self._empty_required_widgets.append(widget)
|
|
||||||
self.xml.get_object('join_button').set_sensitive(False)
|
|
||||||
else:
|
|
||||||
if widget in self._empty_required_widgets:
|
|
||||||
self._empty_required_widgets.remove(widget)
|
|
||||||
if not self._empty_required_widgets and self.account:
|
|
||||||
self.xml.get_object('join_button').set_sensitive(True)
|
|
||||||
text = self._room_jid_entry.get_text()
|
|
||||||
if widget == self._room_jid_entry and text.startswith('xmpp:'):
|
|
||||||
text = text[5:]
|
|
||||||
self._room_jid_entry.set_text(text)
|
|
||||||
if widget == self._room_jid_entry and '@' in text:
|
|
||||||
# Don't allow @ char in room entry
|
|
||||||
room_jid, server = text.split('@', 1)
|
|
||||||
self._room_jid_entry.set_text(room_jid)
|
|
||||||
if server:
|
|
||||||
if '?' in server:
|
|
||||||
server = server.split('?')[0]
|
|
||||||
self.server_comboboxtext.get_child().set_text(server)
|
|
||||||
self.server_comboboxtext.grab_focus()
|
|
||||||
|
|
||||||
def on_account_combobox_changed(self, widget):
|
|
||||||
model = widget.get_model()
|
|
||||||
iter_ = widget.get_active_iter()
|
|
||||||
self.account = model[iter_][0]
|
|
||||||
self.on_required_entry_changed(self._nickname_entry)
|
|
||||||
|
|
||||||
def _set_room_jid(self, full_jid):
|
|
||||||
room_jid, nick = app.get_room_and_nick_from_fjid(full_jid)
|
|
||||||
room, server = app.get_name_and_server_from_jid(room_jid)
|
|
||||||
self._room_jid_entry.set_text(room)
|
|
||||||
model = self.server_comboboxtext.get_model()
|
|
||||||
self.server_comboboxtext.get_child().set_text(server)
|
|
||||||
if nick:
|
|
||||||
self._nickname_entry.set_text(nick)
|
|
||||||
|
|
||||||
def on_recently_combobox_changed(self, widget):
|
|
||||||
model = widget.get_model()
|
|
||||||
iter_ = widget.get_active_iter()
|
|
||||||
full_jid = model[iter_][1]
|
|
||||||
self._set_room_jid(full_jid)
|
|
||||||
|
|
||||||
def on_browse_rooms_button_clicked(self, widget):
|
|
||||||
server = self.server_comboboxtext.get_child().get_text()
|
|
||||||
self.requested_jid = server
|
self.requested_jid = server
|
||||||
app.connections[self.account].discoverInfo(server)
|
app.connections[self.account].discoverInfo(server)
|
||||||
|
|
||||||
|
@ -2552,9 +2589,9 @@ class JoinGroupchatWindow:
|
||||||
if obj.jid != self.requested_jid:
|
if obj.jid != self.requested_jid:
|
||||||
return
|
return
|
||||||
self.requested_jid = None
|
self.requested_jid = None
|
||||||
window = app.interface.instances[self.account]['join_gc'].window
|
ErrorDialog(_('Wrong server'),
|
||||||
ErrorDialog(_('Wrong server'), _('%s is not a groupchat server') % \
|
_('%s is not a groupchat server') % obj.jid,
|
||||||
obj.jid, transient_for=window)
|
transient_for=self)
|
||||||
|
|
||||||
def _nec_agent_info_received(self, obj):
|
def _nec_agent_info_received(self, obj):
|
||||||
if obj.conn.name != self.account:
|
if obj.conn.name != self.account:
|
||||||
|
@ -2563,9 +2600,9 @@ class JoinGroupchatWindow:
|
||||||
return
|
return
|
||||||
self.requested_jid = None
|
self.requested_jid = None
|
||||||
if nbxmpp.NS_MUC not in obj.features:
|
if nbxmpp.NS_MUC not in obj.features:
|
||||||
window = app.interface.instances[self.account]['join_gc'].window
|
ErrorDialog(_('Wrong server'),
|
||||||
ErrorDialog(_('Wrong server'), _('%s is not a groupchat server') % \
|
_('%s is not a groupchat server') % obj.jid,
|
||||||
obj.jid, transient_for=window)
|
transient_for=self)
|
||||||
return
|
return
|
||||||
if obj.jid in app.interface.instances[self.account]['disco']:
|
if obj.jid in app.interface.instances[self.account]['disco']:
|
||||||
app.interface.instances[self.account]['disco'][obj.jid].window.\
|
app.interface.instances[self.account]['disco'][obj.jid].window.\
|
||||||
|
@ -2573,99 +2610,14 @@ class JoinGroupchatWindow:
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
# Object will add itself to the window dict
|
# Object will add itself to the window dict
|
||||||
import disco
|
from gajim.disco import ServiceDiscoveryWindow
|
||||||
disco.ServiceDiscoveryWindow(self.account, obj.jid,
|
ServiceDiscoveryWindow(
|
||||||
|
self.account, obj.jid,
|
||||||
initial_identities=[{'category': 'conference',
|
initial_identities=[{'category': 'conference',
|
||||||
'type': 'text'}])
|
'type': 'text'}])
|
||||||
except GajimGeneralException:
|
except GajimGeneralException:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def on_server_entry_changed(self, widget):
|
|
||||||
if not widget.get_text():
|
|
||||||
self.browse_button.set_sensitive(False)
|
|
||||||
else:
|
|
||||||
self.browse_button.set_sensitive(True)
|
|
||||||
|
|
||||||
def on_cancel_button_clicked(self, widget):
|
|
||||||
"""
|
|
||||||
When Cancel button is clicked
|
|
||||||
"""
|
|
||||||
self.window.destroy()
|
|
||||||
|
|
||||||
def on_bookmark_checkbutton_toggled(self, widget):
|
|
||||||
auto_join_checkbutton = self.xml.get_object('auto_join_checkbutton')
|
|
||||||
if widget.get_active():
|
|
||||||
auto_join_checkbutton.set_sensitive(True)
|
|
||||||
else:
|
|
||||||
auto_join_checkbutton.set_sensitive(False)
|
|
||||||
|
|
||||||
def on_join_button_clicked(self, widget):
|
|
||||||
"""
|
|
||||||
When Join button is clicked
|
|
||||||
"""
|
|
||||||
if not self.account:
|
|
||||||
ErrorDialog(_('Invalid Account'),
|
|
||||||
_('You have to choose an account from which you want to join the '
|
|
||||||
'groupchat.'))
|
|
||||||
return
|
|
||||||
nickname = self._nickname_entry.get_text()
|
|
||||||
server = self.server_comboboxtext.get_child().get_text()
|
|
||||||
room = self._room_jid_entry.get_text().strip()
|
|
||||||
room_jid = room + '@' + server
|
|
||||||
password = self._password_entry.get_text()
|
|
||||||
try:
|
|
||||||
nickname = helpers.parse_resource(nickname)
|
|
||||||
except Exception:
|
|
||||||
ErrorDialog(_('Invalid Nickname'),
|
|
||||||
_('The nickname contains invalid characters.'))
|
|
||||||
return
|
|
||||||
user, server, resource = helpers.decompose_jid(room_jid)
|
|
||||||
if not user or not server or resource:
|
|
||||||
ErrorDialog(_('Invalid group chat JID'),
|
|
||||||
_('Please enter the group chat JID as room@server.'))
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
room_jid = helpers.parse_jid(room_jid)
|
|
||||||
except Exception:
|
|
||||||
ErrorDialog(_('Invalid group chat JID'),
|
|
||||||
_('The group chat JID contains invalid characters.'))
|
|
||||||
return
|
|
||||||
|
|
||||||
if app.contacts.get_contact(self.account, room_jid) and \
|
|
||||||
not app.contacts.get_contact(self.account, room_jid).is_groupchat():
|
|
||||||
ErrorDialog(_('This is not a group chat'),
|
|
||||||
_('%(room_jid)s is already in your roster. Please check if '
|
|
||||||
'%(room_jid)s is a correct group chat name. If it is, delete '
|
|
||||||
'it from your roster and try joining the group chat again.') % \
|
|
||||||
{'room_jid': room_jid, 'room_jid': room_jid})
|
|
||||||
return
|
|
||||||
|
|
||||||
full_jid = room_jid + '/' + nickname
|
|
||||||
if full_jid in self.recently_groupchat:
|
|
||||||
self.recently_groupchat.remove(full_jid)
|
|
||||||
self.recently_groupchat.insert(0, full_jid)
|
|
||||||
if len(self.recently_groupchat) > 10:
|
|
||||||
self.recently_groupchat = self.recently_groupchat[0:10]
|
|
||||||
app.config.set('recently_groupchat',
|
|
||||||
' '.join(self.recently_groupchat))
|
|
||||||
|
|
||||||
if self.xml.get_object('bookmark_checkbutton').get_active():
|
|
||||||
if self.xml.get_object('auto_join_checkbutton').get_active():
|
|
||||||
autojoin = '1'
|
|
||||||
else:
|
|
||||||
autojoin = '0'
|
|
||||||
# Add as bookmark, with autojoin and not minimized
|
|
||||||
name = app.get_nick_from_jid(room_jid)
|
|
||||||
app.interface.add_gc_bookmark(self.account, name, room_jid,
|
|
||||||
autojoin, autojoin, password, nickname)
|
|
||||||
|
|
||||||
if self.automatic:
|
|
||||||
app.automatic_rooms[self.account][room_jid] = self.automatic
|
|
||||||
|
|
||||||
app.interface.join_gc_room(self.account, room_jid, nickname, password)
|
|
||||||
|
|
||||||
self.window.destroy()
|
|
||||||
|
|
||||||
class SynchroniseSelectAccountDialog:
|
class SynchroniseSelectAccountDialog:
|
||||||
def __init__(self, account):
|
def __init__(self, account):
|
||||||
# 'account' can be None if we are about to create our first one
|
# 'account' can be None if we are about to create our first one
|
||||||
|
@ -2807,59 +2759,323 @@ class SynchroniseSelectContactsDialog:
|
||||||
iter_ = model.iter_next(iter_)
|
iter_ = model.iter_next(iter_)
|
||||||
self.dialog.destroy()
|
self.dialog.destroy()
|
||||||
|
|
||||||
class NewChatDialog(InputDialog):
|
class StartChatDialog(Gtk.ApplicationWindow):
|
||||||
def __init__(self, account):
|
def __init__(self):
|
||||||
self.account = account
|
# Must be before ApplicationWindow.__init__
|
||||||
|
# or we get our own window
|
||||||
|
active_window = app.app.get_active_window()
|
||||||
|
|
||||||
if len(app.connections) > 1:
|
Gtk.ApplicationWindow.__init__(self)
|
||||||
title = _('Start Chat with account %s') % account
|
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:
|
else:
|
||||||
title = _('Start Chat')
|
self.set_transient_for(active_window)
|
||||||
prompt_text = _('Fill in the nickname or the JID of the contact you '
|
self.set_type_hint(Gdk.WindowTypeHint.DIALOG)
|
||||||
'would like\nto send a chat message to:')
|
self.set_show_menubar(False)
|
||||||
InputDialog.__init__(self, title, prompt_text, is_modal=False)
|
self.set_title(_('Start new Conversation'))
|
||||||
self.input_entry.set_placeholder_text(_('Nickname / JID'))
|
self.set_default_size(-1, 400)
|
||||||
|
|
||||||
self.completion_dict = {}
|
self.builder = gtkgui_helpers.get_gtk_builder(
|
||||||
liststore = gtkgui_helpers.get_completion_liststore(self.input_entry)
|
'start_chat_dialog.ui')
|
||||||
self.completion_dict = helpers.get_contact_dict_for_account(account)
|
self.listbox = self.builder.get_object('listbox')
|
||||||
# add all contacts to the model
|
self.search_entry = self.builder.get_object('search_entry')
|
||||||
keys = sorted(self.completion_dict.keys())
|
self.box = self.builder.get_object('box')
|
||||||
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.ok_handler = self.new_chat_response
|
self.add(self.box)
|
||||||
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()
|
|
||||||
|
|
||||||
def new_chat_response(self, jid):
|
self.new_contact_row_visible = False
|
||||||
"""
|
self.new_contact_rows = {}
|
||||||
Called when ok button is clicked
|
self.new_groupchat_rows = {}
|
||||||
"""
|
self.accounts = app.connections.keys()
|
||||||
if app.connections[self.account].connected <= 1:
|
self.add_contacts()
|
||||||
#if offline or connecting
|
self.add_groupchats()
|
||||||
ErrorDialog(_('Connection not available'),
|
|
||||||
_('Please make sure you are connected with "%s".') % self.account)
|
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
|
return
|
||||||
|
|
||||||
if jid in self.completion_dict:
|
|
||||||
jid = self.completion_dict[jid].jid
|
|
||||||
else:
|
|
||||||
try:
|
try:
|
||||||
jid = helpers.parse_jid(jid)
|
helpers.parse_jid(row.jid)
|
||||||
except helpers.InvalidFormat as e:
|
except helpers.InvalidFormat as e:
|
||||||
ErrorDialog(_('Invalid JID'), str(e))
|
ErrorDialog(_('Invalid JID'), str(e), transient_for=self)
|
||||||
return
|
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
|
return
|
||||||
app.interface.new_chat_from_jid(self.account, jid)
|
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
|
||||||
|
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:
|
class ChangePasswordDialog:
|
||||||
def __init__(self, account, on_response, transient_for=None):
|
def __init__(self, account, on_response, transient_for=None):
|
||||||
|
@ -4476,16 +4692,13 @@ class InvitationReceivedDialog:
|
||||||
sectext += '\n\n' + _('Do you want to accept the invitation?')
|
sectext += '\n\n' + _('Do you want to accept the invitation?')
|
||||||
|
|
||||||
def on_yes(checked, text):
|
def on_yes(checked, text):
|
||||||
try:
|
|
||||||
if self.is_continued:
|
if self.is_continued:
|
||||||
app.interface.join_gc_room(self.account, self.room_jid,
|
app.interface.join_gc_room(self.account, self.room_jid,
|
||||||
app.nicks[self.account], self.password,
|
app.nicks[self.account], self.password,
|
||||||
is_continued=True)
|
is_continued=True)
|
||||||
else:
|
else:
|
||||||
JoinGroupchatWindow(self.account, self.room_jid,
|
app.interface.join_gc_minimal(
|
||||||
password=self.password)
|
self.account, self.room_jid, password=self.password)
|
||||||
except GajimGeneralException:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def on_no(text):
|
def on_no(text):
|
||||||
app.connections[account].decline_invitation(self.room_jid,
|
app.connections[account].decline_invitation(self.room_jid,
|
||||||
|
@ -4828,7 +5041,7 @@ class TransformChatToMUC:
|
||||||
if 'jabber' in app.connections[account].muc_jid:
|
if 'jabber' in app.connections[account].muc_jid:
|
||||||
server_list.append(app.connections[account].muc_jid['jabber'])
|
server_list.append(app.connections[account].muc_jid['jabber'])
|
||||||
# add servers or recently joined groupchats
|
# add servers or recently joined groupchats
|
||||||
recently_groupchat = app.config.get('recently_groupchat').split()
|
recently_groupchat = app.config.get_per('accounts', account, 'recent_groupchats').split()
|
||||||
for g in recently_groupchat:
|
for g in recently_groupchat:
|
||||||
server = app.get_server_from_jid(g)
|
server = app.get_server_from_jid(g)
|
||||||
if server not in server_list and not server.startswith('irc'):
|
if server not in server_list and not server.startswith('irc'):
|
||||||
|
|
|
@ -1400,13 +1400,7 @@ class ToplevelAgentBrowser(AgentBrowser):
|
||||||
if not iter_:
|
if not iter_:
|
||||||
return
|
return
|
||||||
service = model[iter_][0]
|
service = model[iter_][0]
|
||||||
if 'join_gc' not in app.interface.instances[self.account]:
|
app.interface.join_gc_minimal(self.account, service)
|
||||||
try:
|
|
||||||
dialogs.JoinGroupchatWindow(self.account, service)
|
|
||||||
except GajimGeneralException:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
app.interface.instances[self.account]['join_gc'].window.present()
|
|
||||||
|
|
||||||
def update_actions(self):
|
def update_actions(self):
|
||||||
if self.execute_button:
|
if self.execute_button:
|
||||||
|
@ -1810,14 +1804,11 @@ class MucBrowser(AgentBrowser):
|
||||||
return
|
return
|
||||||
service = model[iter_][0]
|
service = model[iter_][0]
|
||||||
if 'join_gc' not in app.interface.instances[self.account]:
|
if 'join_gc' not in app.interface.instances[self.account]:
|
||||||
try:
|
app.interface.join_gc_minimal(self.account, service)
|
||||||
dialogs.JoinGroupchatWindow(self.account, service)
|
|
||||||
except GajimGeneralException:
|
|
||||||
pass
|
|
||||||
else:
|
else:
|
||||||
app.interface.instances[self.account]['join_gc']._set_room_jid(
|
app.interface.instances[self.account]['join_gc'].set_room(service)
|
||||||
service)
|
app.interface.instances[self.account]['join_gc'].present()
|
||||||
app.interface.instances[self.account]['join_gc'].window.present()
|
self.window.destroy()
|
||||||
|
|
||||||
def update_actions(self):
|
def update_actions(self):
|
||||||
sens = self.window.services_treeview.get_selection().count_selected_rows()
|
sens = self.window.services_treeview.get_selection().count_selected_rows()
|
||||||
|
|
|
@ -60,7 +60,8 @@ class GajimApplication(Gtk.Application):
|
||||||
'''Main class handling activation and command line.'''
|
'''Main class handling activation and command line.'''
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Gtk.Application.__init__(self, application_id='org.gajim.Gajim')
|
Gtk.Application.__init__(self, application_id='org.gajim.Gajim',
|
||||||
|
flags=Gio.ApplicationFlags.HANDLES_OPEN)
|
||||||
|
|
||||||
self.add_main_option('version', ord('V'), GLib.OptionFlags.NONE,
|
self.add_main_option('version', ord('V'), GLib.OptionFlags.NONE,
|
||||||
GLib.OptionArg.NONE,
|
GLib.OptionArg.NONE,
|
||||||
|
@ -89,13 +90,11 @@ class GajimApplication(Gtk.Application):
|
||||||
self.add_main_option('warnings', ord('w'), GLib.OptionFlags.NONE,
|
self.add_main_option('warnings', ord('w'), GLib.OptionFlags.NONE,
|
||||||
GLib.OptionArg.NONE,
|
GLib.OptionArg.NONE,
|
||||||
_('Show all warnings'))
|
_('Show all warnings'))
|
||||||
self.add_main_option(GLib.OPTION_REMAINING, 0, GLib.OptionFlags.HIDDEN,
|
|
||||||
GLib.OptionArg.STRING_ARRAY,
|
|
||||||
"")
|
|
||||||
|
|
||||||
self.connect('handle-local-options', self._handle_local_options)
|
self.connect('handle-local-options', self._handle_local_options)
|
||||||
self.connect('startup', self._startup)
|
self.connect('startup', self._startup)
|
||||||
self.connect('activate', self._activate)
|
self.connect('activate', self._activate)
|
||||||
|
self.connect('open', self._open)
|
||||||
|
|
||||||
self.profile = ''
|
self.profile = ''
|
||||||
self.config_path = None
|
self.config_path = None
|
||||||
|
@ -235,6 +234,28 @@ class GajimApplication(Gtk.Application):
|
||||||
from gajim import gui_menu_builder
|
from gajim import gui_menu_builder
|
||||||
gui_menu_builder.build_accounts_menu()
|
gui_menu_builder.build_accounts_menu()
|
||||||
|
|
||||||
|
def _open(self, application, file, hint, *args):
|
||||||
|
for arg in file:
|
||||||
|
uri = arg.get_uri()
|
||||||
|
# remove xmpp:///
|
||||||
|
uri = uri[8:]
|
||||||
|
jid, cmd = uri.split('?')
|
||||||
|
if cmd == 'join':
|
||||||
|
self.interface.join_gc_minimal(None, jid)
|
||||||
|
elif cmd == 'roster':
|
||||||
|
self.activate_action('add-contact', GLib.Variant('s', jid))
|
||||||
|
elif cmd == 'message':
|
||||||
|
from gajim.common import app
|
||||||
|
accounts = list(app.connections.keys())
|
||||||
|
if not accounts:
|
||||||
|
continue
|
||||||
|
if len(accounts) == 1:
|
||||||
|
app.interface.new_chat_from_jid(accounts[0], jid)
|
||||||
|
else:
|
||||||
|
self.activate_action('start-chat')
|
||||||
|
start_chat_window = app.interface.instances['start_chat']
|
||||||
|
start_chat_window.search_entry.set_text(jid)
|
||||||
|
|
||||||
def do_shutdown(self, *args):
|
def do_shutdown(self, *args):
|
||||||
Gtk.Application.do_shutdown(self)
|
Gtk.Application.do_shutdown(self)
|
||||||
# Shutdown GUI and save config
|
# Shutdown GUI and save config
|
||||||
|
@ -274,10 +295,6 @@ class GajimApplication(Gtk.Application):
|
||||||
logging_helpers.set_loglevels(loglevel)
|
logging_helpers.set_loglevels(loglevel)
|
||||||
if options.contains('warnings'):
|
if options.contains('warnings'):
|
||||||
self.show_warnings()
|
self.show_warnings()
|
||||||
if options.contains(GLib.OPTION_REMAINING):
|
|
||||||
unhandled = options.lookup_value(GLib.OPTION_REMAINING).get_strv()
|
|
||||||
print('Error: Unhandled arguments: %s' % unhandled)
|
|
||||||
return 0
|
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
def show_warnings(self):
|
def show_warnings(self):
|
||||||
|
@ -301,7 +318,6 @@ class GajimApplication(Gtk.Application):
|
||||||
|
|
||||||
self.account_actions = [
|
self.account_actions = [
|
||||||
('-start-single-chat', action.on_single_message, 'online', 's'),
|
('-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'),
|
('-join-groupchat', action.on_join_gc, 'online', 's'),
|
||||||
('-add-contact', action.on_add_contact, 'online', 's'),
|
('-add-contact', action.on_add_contact, 'online', 's'),
|
||||||
('-services', action.on_service_disco, 'online', 's'),
|
('-services', action.on_service_disco, 'online', 's'),
|
||||||
|
@ -342,6 +358,7 @@ class GajimApplication(Gtk.Application):
|
||||||
('accounts', action.on_accounts),
|
('accounts', action.on_accounts),
|
||||||
('add-account', action.on_add_account),
|
('add-account', action.on_add_account),
|
||||||
('manage-proxies', action.on_manage_proxies),
|
('manage-proxies', action.on_manage_proxies),
|
||||||
|
('start-chat', action.on_new_chat),
|
||||||
('bookmarks', action.on_manage_bookmarks),
|
('bookmarks', action.on_manage_bookmarks),
|
||||||
('history-manager', action.on_history_manager),
|
('history-manager', action.on_history_manager),
|
||||||
('preferences', action.on_preferences),
|
('preferences', action.on_preferences),
|
||||||
|
@ -355,6 +372,10 @@ class GajimApplication(Gtk.Application):
|
||||||
('faq', action.on_faq),
|
('faq', action.on_faq),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
act = Gio.SimpleAction.new('add-contact', GLib.VariantType.new('s'))
|
||||||
|
act.connect("activate", action.on_add_contact_jid)
|
||||||
|
self.add_action(act)
|
||||||
|
|
||||||
for action in self.general_actions:
|
for action in self.general_actions:
|
||||||
action_name, func = action
|
action_name, func = action
|
||||||
act = Gio.SimpleAction.new(action_name, None)
|
act = Gio.SimpleAction.new(action_name, None)
|
||||||
|
|
|
@ -125,18 +125,6 @@ class GajimRemote:
|
||||||
' "sync with global status" option set'), False)
|
' "sync with global status" option set'), False)
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'open_chat': [
|
|
||||||
_('Shows the chat dialog so that you can send messages to a contact'),
|
|
||||||
[
|
|
||||||
('jid', _('JID of the contact that you want to chat with'),
|
|
||||||
True),
|
|
||||||
(Q_('?CLI:account'), _('if specified, contact is taken from the '
|
|
||||||
'contact list of this account'), False),
|
|
||||||
(Q_('?CLI:message'),
|
|
||||||
_('message content. The account must be specified or ""'),
|
|
||||||
False)
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'send_chat_message': [
|
'send_chat_message': [
|
||||||
_('Sends new chat message to a contact in the roster. Both OpenPGP key '
|
_('Sends new chat message to a contact in the roster. Both OpenPGP key '
|
||||||
'and account are optional. If you want to set only \'account\', '
|
'and account are optional. If you want to set only \'account\', '
|
||||||
|
@ -225,13 +213,6 @@ class GajimRemote:
|
||||||
|
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'add_contact': [
|
|
||||||
_('Adds contact to roster'),
|
|
||||||
[
|
|
||||||
(_('jid'), _('JID of the contact'), True),
|
|
||||||
(Q_('?CLI:account'), _('Adds new contact to this account'), False)
|
|
||||||
]
|
|
||||||
],
|
|
||||||
|
|
||||||
'get_status': [
|
'get_status': [
|
||||||
_('Returns current status (the global one unless account is specified)'),
|
_('Returns current status (the global one unless account is specified)'),
|
||||||
|
@ -251,12 +232,7 @@ class GajimRemote:
|
||||||
_('Returns number of unread messages'),
|
_('Returns number of unread messages'),
|
||||||
[ ]
|
[ ]
|
||||||
],
|
],
|
||||||
'start_chat': [
|
|
||||||
_('Opens \'Start Chat\' dialog'),
|
|
||||||
[
|
|
||||||
(Q_('?CLI:account'), _('Starts chat, using this account'), True)
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'send_xml': [
|
'send_xml': [
|
||||||
_('Sends custom XML'),
|
_('Sends custom XML'),
|
||||||
[
|
[
|
||||||
|
@ -275,25 +251,7 @@ class GajimRemote:
|
||||||
False)
|
False)
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'handle_uri': [
|
|
||||||
_('Handle a xmpp:/ URI'),
|
|
||||||
[
|
|
||||||
(Q_('?CLI:uri'), _('URI to handle'), True),
|
|
||||||
(Q_('?CLI:account'), _('Account in which you want to handle it'),
|
|
||||||
False),
|
|
||||||
(Q_('?CLI:message'), _('Message content'), False)
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'join_room': [
|
|
||||||
_('Join a MUC room'),
|
|
||||||
[
|
|
||||||
(Q_('?CLI:room'), _('Room JID'), True),
|
|
||||||
(Q_('?CLI:nick'), _('Nickname to use'), False),
|
|
||||||
(Q_('?CLI:password'), _('Password to enter the room'), False),
|
|
||||||
(Q_('?CLI:account'), _('Account from which you want to enter the '
|
|
||||||
'room'), False)
|
|
||||||
]
|
|
||||||
],
|
|
||||||
'check_gajim_running': [
|
'check_gajim_running': [
|
||||||
_('Check if Gajim is running'),
|
_('Check if Gajim is running'),
|
||||||
[]
|
[]
|
||||||
|
@ -317,8 +275,6 @@ class GajimRemote:
|
||||||
else:
|
else:
|
||||||
print(self.compose_help().encode(PREFERRED_ENCODING))
|
print(self.compose_help().encode(PREFERRED_ENCODING))
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
if self.command == 'handle_uri':
|
|
||||||
self.handle_uri()
|
|
||||||
if self.command == 'check_gajim_running':
|
if self.command == 'check_gajim_running':
|
||||||
print(self.check_gajim_running())
|
print(self.check_gajim_running())
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
@ -342,9 +298,7 @@ class GajimRemote:
|
||||||
Print retrieved result to the output
|
Print retrieved result to the output
|
||||||
"""
|
"""
|
||||||
if res is not None:
|
if res is not None:
|
||||||
if self.command in ('open_chat', 'send_chat_message',
|
if self.command in ('send_chat_message', 'send_single_message'):
|
||||||
'send_single_message', 'start_chat'):
|
|
||||||
if self.command in ('send_message', 'send_single_message'):
|
|
||||||
self.argv_len -= 2
|
self.argv_len -= 2
|
||||||
|
|
||||||
if res is False:
|
if res is False:
|
||||||
|
@ -533,66 +487,6 @@ class GajimRemote:
|
||||||
# add empty string for missing args
|
# add empty string for missing args
|
||||||
self.arguments += ['']*(len(args)-i)
|
self.arguments += ['']*(len(args)-i)
|
||||||
|
|
||||||
def handle_uri(self):
|
|
||||||
if len(sys.argv) < 3:
|
|
||||||
send_error(_('No URI given'))
|
|
||||||
if not sys.argv[2].startswith('xmpp:'):
|
|
||||||
send_error(_('Wrong URI'))
|
|
||||||
sys.argv[2] = sys.argv[2][5:]
|
|
||||||
uri = sys.argv[2]
|
|
||||||
if not '?' in uri:
|
|
||||||
self.command = sys.argv[1] = 'open_chat'
|
|
||||||
return
|
|
||||||
jid, args = uri.split('?', 1)
|
|
||||||
try:
|
|
||||||
jid = urllib.parse.unquote(jid)
|
|
||||||
except UnicodeDecodeError:
|
|
||||||
pass
|
|
||||||
args = args.split(';')
|
|
||||||
action = None
|
|
||||||
options = {}
|
|
||||||
if args:
|
|
||||||
action = args[0]
|
|
||||||
for arg in args[1:]:
|
|
||||||
opt = arg.split('=', 1)
|
|
||||||
if len(opt) != 2:
|
|
||||||
continue
|
|
||||||
options[opt[0]] = opt[1]
|
|
||||||
|
|
||||||
if action == 'message':
|
|
||||||
self.command = sys.argv[1] = 'open_chat'
|
|
||||||
sys.argv[2] = jid
|
|
||||||
if 'body' in options:
|
|
||||||
# Open chat window and paste the text in the input message
|
|
||||||
# dialog
|
|
||||||
message = options['body']
|
|
||||||
try:
|
|
||||||
message = urllib.parse.unquote(message)
|
|
||||||
except UnicodeDecodeError:
|
|
||||||
pass
|
|
||||||
if len(sys.argv) == 4:
|
|
||||||
# jid in the sys.argv
|
|
||||||
sys.argv.append(message)
|
|
||||||
else:
|
|
||||||
sys.argv.append('')
|
|
||||||
sys.argv.append(message)
|
|
||||||
sys.argv[3] = ''
|
|
||||||
sys.argv[4] = message
|
|
||||||
return
|
|
||||||
sys.argv[2] = jid
|
|
||||||
if action == 'join':
|
|
||||||
self.command = sys.argv[1] = 'join_room'
|
|
||||||
# Move account parameter from position 3 to 5
|
|
||||||
sys.argv.append('')
|
|
||||||
sys.argv.append(sys.argv[3])
|
|
||||||
sys.argv[3] = ''
|
|
||||||
return
|
|
||||||
if action == 'roster':
|
|
||||||
# Add contact to roster
|
|
||||||
self.command = sys.argv[1] = 'add_contact'
|
|
||||||
return
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
def call_remote_method(self):
|
def call_remote_method(self):
|
||||||
"""
|
"""
|
||||||
Calls self.method with arguments from sys.argv[2:]
|
Calls self.method with arguments from sys.argv[2:]
|
||||||
|
|
|
@ -101,6 +101,7 @@ from gajim import profile_window
|
||||||
from gajim import config
|
from gajim import config
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from gajim.common import ged
|
from gajim.common import ged
|
||||||
|
from gajim.common.caps_cache import muc_caps_cache
|
||||||
|
|
||||||
from gajim.common.configpaths import gajimpaths
|
from gajim.common.configpaths import gajimpaths
|
||||||
config_filename = gajimpaths['CONFIG_FILE']
|
config_filename = gajimpaths['CONFIG_FILE']
|
||||||
|
@ -1757,6 +1758,49 @@ class Interface:
|
||||||
tv = ctrl.conv_textview
|
tv = ctrl.conv_textview
|
||||||
tv.scroll_to_end_iter()
|
tv.scroll_to_end_iter()
|
||||||
|
|
||||||
|
def join_gc_minimal(self, account, room_jid, password=None):
|
||||||
|
if account is not None:
|
||||||
|
if app.in_groupchat(account, room_jid):
|
||||||
|
# If we already in the groupchat, join_gc_room will bring
|
||||||
|
# it to front
|
||||||
|
app.interface.join_gc_room(account, room_jid, '', '')
|
||||||
|
return
|
||||||
|
|
||||||
|
for bookmark in app.connections[account].bookmarks:
|
||||||
|
if bookmark['jid'] != room_jid:
|
||||||
|
continue
|
||||||
|
app.interface.join_gc_room(
|
||||||
|
account, room_jid, bookmark['nick'], bookmark['password'])
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
room_jid = helpers.parse_jid(room_jid)
|
||||||
|
except helpers.InvalidFormat:
|
||||||
|
dialogs.ErrorDialog('Invalid JID',
|
||||||
|
transient_for=app.app.get_active_window())
|
||||||
|
return
|
||||||
|
|
||||||
|
connected_accounts = app.get_connected_accounts()
|
||||||
|
if account is not None and account not in connected_accounts:
|
||||||
|
connected_accounts = None
|
||||||
|
if not connected_accounts:
|
||||||
|
dialogs.ErrorDialog(
|
||||||
|
_('You are not connected to the server'),
|
||||||
|
_('You can not join a group chat unless you are connected.'),
|
||||||
|
transient_for=app.app.get_active_window())
|
||||||
|
return
|
||||||
|
|
||||||
|
def _on_discover_result():
|
||||||
|
if not muc_caps_cache.is_cached(room_jid):
|
||||||
|
dialogs.ErrorDialog(_('JID is not a Groupchat'),
|
||||||
|
transient_for=app.app.get_active_window())
|
||||||
|
return
|
||||||
|
dialogs.JoinGroupchatWindow(account, room_jid, password=password)
|
||||||
|
|
||||||
|
disco_account = connected_accounts[0] if account is None else account
|
||||||
|
app.connections[disco_account].discoverMUC(
|
||||||
|
room_jid, _on_discover_result)
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
### Methods dealing with emoticons
|
### Methods dealing with emoticons
|
||||||
################################################################################
|
################################################################################
|
||||||
|
@ -1953,8 +1997,6 @@ class Interface:
|
||||||
win.set_active_tab(gc_ctrl)
|
win.set_active_tab(gc_ctrl)
|
||||||
else:
|
else:
|
||||||
self.roster.on_groupchat_maximized(None, room_jid, account)
|
self.roster.on_groupchat_maximized(None, room_jid, account)
|
||||||
dialogs.ErrorDialog(_('You are already in group chat %s') % \
|
|
||||||
room_jid)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
invisible_show = app.SHOW_LIST.index('invisible')
|
invisible_show = app.SHOW_LIST.index('invisible')
|
||||||
|
@ -2130,6 +2172,7 @@ class Interface:
|
||||||
### Other Methods
|
### Other Methods
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def change_awn_icon_status(status):
|
def change_awn_icon_status(status):
|
||||||
if not dbus_support.supported:
|
if not dbus_support.supported:
|
||||||
|
@ -2403,8 +2446,8 @@ class Interface:
|
||||||
pixbuf = None
|
pixbuf = None
|
||||||
try:
|
try:
|
||||||
if size is not None:
|
if size is not None:
|
||||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
|
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
|
||||||
path, size, size)
|
path, size, size, False)
|
||||||
else:
|
else:
|
||||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file(path)
|
pixbuf = GdkPixbuf.Pixbuf.new_from_file(path)
|
||||||
except GLib.GError as error:
|
except GLib.GError as error:
|
||||||
|
@ -2471,10 +2514,6 @@ class Interface:
|
||||||
# check for duplicate entry and respect alpha order
|
# check for duplicate entry and respect alpha order
|
||||||
for bookmark in app.connections[account].bookmarks:
|
for bookmark in app.connections[account].bookmarks:
|
||||||
if bookmark['jid'] == bm['jid']:
|
if bookmark['jid'] == bm['jid']:
|
||||||
dialogs.ErrorDialog(
|
|
||||||
_('Bookmark already set'),
|
|
||||||
_('Group Chat "%s" is already in your bookmarks.') % \
|
|
||||||
bm['jid'])
|
|
||||||
return
|
return
|
||||||
if bookmark['name'] > bm['name']:
|
if bookmark['name'] > bm['name']:
|
||||||
place_found = True
|
place_found = True
|
||||||
|
@ -2486,10 +2525,6 @@ class Interface:
|
||||||
app.connections[account].bookmarks.append(bm)
|
app.connections[account].bookmarks.append(bm)
|
||||||
app.connections[account].store_bookmarks()
|
app.connections[account].store_bookmarks()
|
||||||
gui_menu_builder.build_bookmark_menu(account)
|
gui_menu_builder.build_bookmark_menu(account)
|
||||||
dialogs.InformationDialog(
|
|
||||||
_('Bookmark has been added successfully'),
|
|
||||||
_('You can manage your bookmarks via Actions menu in your roster.'))
|
|
||||||
|
|
||||||
|
|
||||||
# does JID exist only within a groupchat?
|
# does JID exist only within a groupchat?
|
||||||
def is_pm_contact(self, fjid, account):
|
def is_pm_contact(self, fjid, account):
|
||||||
|
|
|
@ -722,7 +722,6 @@ def get_account_menu(account):
|
||||||
('-join-groupchat', _('Join Group Chat')),
|
('-join-groupchat', _('Join Group Chat')),
|
||||||
('-profile', _('Profile')),
|
('-profile', _('Profile')),
|
||||||
('-services', _('Discover Services')),
|
('-services', _('Discover Services')),
|
||||||
('-start-chat', _('Start Chat...')),
|
|
||||||
('-start-single-chat', _('Send Single Message...')),
|
('-start-single-chat', _('Send Single Message...')),
|
||||||
('Advanced', [
|
('Advanced', [
|
||||||
('-archive', _('Archiving Preferences')),
|
('-archive', _('Archiving Preferences')),
|
||||||
|
|
|
@ -915,10 +915,7 @@ class HtmlTextView(Gtk.TextView):
|
||||||
# app.interface.new_chat_from_jid(self.account, jid)
|
# app.interface.new_chat_from_jid(self.account, jid)
|
||||||
|
|
||||||
def on_join_group_chat_menuitem_activate(self, widget, room_jid):
|
def on_join_group_chat_menuitem_activate(self, widget, room_jid):
|
||||||
try:
|
dialogs.JoinGroupchatWindow(None, room_jid)
|
||||||
dialogs.JoinGroupchatWindow(room_jid=room_jid)
|
|
||||||
except GajimGeneralException:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def on_add_to_roster_activate(self, widget, jid):
|
def on_add_to_roster_activate(self, widget, jid):
|
||||||
dialogs.AddNewContactWindow(self.account, jid)
|
dialogs.AddNewContactWindow(self.account, jid)
|
||||||
|
|
|
@ -35,7 +35,7 @@ import mimetypes
|
||||||
from gajim.common import app
|
from gajim.common import app
|
||||||
from gajim.common import helpers
|
from gajim.common import helpers
|
||||||
from time import time
|
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 import ged
|
||||||
from gajim.common.connection_handlers_events import MessageOutgoingEvent
|
from gajim.common.connection_handlers_events import MessageOutgoingEvent
|
||||||
from gajim.common.connection_handlers_events import GcMessageOutgoingEvent
|
from gajim.common.connection_handlers_events import GcMessageOutgoingEvent
|
||||||
|
@ -849,7 +849,7 @@ class SignalObject(dbus.service.Object):
|
||||||
if not account:
|
if not account:
|
||||||
# error is shown in gajim-remote check_arguments(..)
|
# error is shown in gajim-remote check_arguments(..)
|
||||||
return DBUS_BOOLEAN(False)
|
return DBUS_BOOLEAN(False)
|
||||||
NewChatDialog(account)
|
app.app.activate_action('start-chat')
|
||||||
return DBUS_BOOLEAN(True)
|
return DBUS_BOOLEAN(True)
|
||||||
|
|
||||||
@dbus.service.method(INTERFACE, in_signature='ss', out_signature='')
|
@dbus.service.method(INTERFACE, in_signature='ss', out_signature='')
|
||||||
|
@ -908,8 +908,6 @@ class SignalObject(dbus.service.Object):
|
||||||
return
|
return
|
||||||
|
|
||||||
if not nick:
|
if not nick:
|
||||||
nick = ''
|
app.interface.join_gc_minimal(account, room_jid)
|
||||||
app.interface.instances[account]['join_gc'] = \
|
|
||||||
JoinGroupchatWindow(account, room_jid, nick)
|
|
||||||
else:
|
else:
|
||||||
app.interface.join_gc_room(account, room_jid, nick, password)
|
app.interface.join_gc_room(account, room_jid, nick, password)
|
||||||
|
|
|
@ -3091,15 +3091,11 @@ class RosterWindow:
|
||||||
if app.connections[account].muc_jid[type_]:
|
if app.connections[account].muc_jid[type_]:
|
||||||
# create the room on this muc server
|
# create the room on this muc server
|
||||||
if 'join_gc' in app.interface.instances[account]:
|
if 'join_gc' in app.interface.instances[account]:
|
||||||
app.interface.instances[account]['join_gc'].window.\
|
app.interface.instances[account]['join_gc'].destroy()
|
||||||
destroy()
|
else:
|
||||||
try:
|
|
||||||
app.interface.instances[account]['join_gc'] = \
|
app.interface.instances[account]['join_gc'] = \
|
||||||
dialogs.JoinGroupchatWindow(account,
|
dialogs.JoinGroupchatWindow(
|
||||||
app.connections[account].muc_jid[type_],
|
account, None, automatic={'invities': jid_list})
|
||||||
automatic = {'invities': jid_list})
|
|
||||||
except GajimGeneralException:
|
|
||||||
continue
|
|
||||||
break
|
break
|
||||||
|
|
||||||
def on_invite_to_room(self, widget, list_, room_jid, room_account,
|
def on_invite_to_room(self, widget, list_, room_jid, room_account,
|
||||||
|
@ -3676,16 +3672,10 @@ class RosterWindow:
|
||||||
'invisible'))
|
'invisible'))
|
||||||
return
|
return
|
||||||
if 'join_gc' in app.interface.instances[account]:
|
if 'join_gc' in app.interface.instances[account]:
|
||||||
app.interface.instances[account]['join_gc'].window.present()
|
app.interface.instances[account]['join_gc'].present()
|
||||||
else:
|
else:
|
||||||
try:
|
|
||||||
app.interface.instances[account]['join_gc'] = \
|
app.interface.instances[account]['join_gc'] = \
|
||||||
dialogs.JoinGroupchatWindow(account)
|
dialogs.JoinGroupchatWindow(account, None)
|
||||||
except GajimGeneralException:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def on_new_chat_menuitem_activate(self, widget, account):
|
|
||||||
dialogs.NewChatDialog(account)
|
|
||||||
|
|
||||||
def on_show_transports_action(self, action, param):
|
def on_show_transports_action(self, action, param):
|
||||||
app.config.set('show_transports_group', param.get_boolean())
|
app.config.set('show_transports_group', param.get_boolean())
|
||||||
|
@ -4934,7 +4924,6 @@ class RosterWindow:
|
||||||
account_context_menu = xml.get_object('account_context_menu')
|
account_context_menu = xml.get_object('account_context_menu')
|
||||||
|
|
||||||
status_menuitem = xml.get_object('status_menuitem')
|
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 = xml.get_object(
|
||||||
'join_group_chat_menuitem')
|
'join_group_chat_menuitem')
|
||||||
add_contact_menuitem = xml.get_object('add_contact_menuitem')
|
add_contact_menuitem = xml.get_object('add_contact_menuitem')
|
||||||
|
@ -5022,9 +5011,6 @@ class RosterWindow:
|
||||||
execute_command_menuitem.connect('activate',
|
execute_command_menuitem.connect('activate',
|
||||||
self.on_execute_command, contact, account)
|
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
|
gc_sub_menu = Gtk.Menu() # gc is always a submenu
|
||||||
join_group_chat_menuitem.set_submenu(gc_sub_menu)
|
join_group_chat_menuitem.set_submenu(gc_sub_menu)
|
||||||
self.add_bookmarks_list(gc_sub_menu, account)
|
self.add_bookmarks_list(gc_sub_menu, account)
|
||||||
|
@ -5033,7 +5019,7 @@ class RosterWindow:
|
||||||
if app.connections[account].connected < 2:
|
if app.connections[account].connected < 2:
|
||||||
for widget in (add_contact_menuitem, service_discovery_menuitem,
|
for widget in (add_contact_menuitem, service_discovery_menuitem,
|
||||||
join_group_chat_menuitem, execute_command_menuitem,
|
join_group_chat_menuitem, execute_command_menuitem,
|
||||||
pep_menuitem, start_chat_menuitem):
|
pep_menuitem):
|
||||||
widget.set_sensitive(False)
|
widget.set_sensitive(False)
|
||||||
else:
|
else:
|
||||||
xml = gtkgui_helpers.get_gtk_builder('zeroconf_context_menu.ui')
|
xml = gtkgui_helpers.get_gtk_builder('zeroconf_context_menu.ui')
|
||||||
|
|
|
@ -185,7 +185,7 @@ class StatusIcon:
|
||||||
dialogs.SingleMessageWindow(account, action='send')
|
dialogs.SingleMessageWindow(account, action='send')
|
||||||
|
|
||||||
def on_new_chat(self, widget, account):
|
def on_new_chat(self, widget, account):
|
||||||
dialogs.NewChatDialog(account)
|
app.app.activate_action('start-chat')
|
||||||
|
|
||||||
def make_menu(self, event_button, event_time):
|
def make_menu(self, event_button, event_time):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -628,7 +628,7 @@ if dbus_support.supported:
|
||||||
if not account:
|
if not account:
|
||||||
# error is shown in gajim-remote check_arguments(..)
|
# error is shown in gajim-remote check_arguments(..)
|
||||||
return DBUS_BOOLEAN(False)
|
return DBUS_BOOLEAN(False)
|
||||||
NewChatDialog(account)
|
app.app.activate_action('start-chat')
|
||||||
return DBUS_BOOLEAN(True)
|
return DBUS_BOOLEAN(True)
|
||||||
|
|
||||||
@dbus.service.method(INTERFACE, in_signature='ss', out_signature='')
|
@dbus.service.method(INTERFACE, in_signature='ss', out_signature='')
|
||||||
|
@ -651,16 +651,14 @@ if dbus_support.supported:
|
||||||
if not account:
|
if not account:
|
||||||
return
|
return
|
||||||
if not nick:
|
if not nick:
|
||||||
nick = ''
|
gajim.interface.join_gc_minimal(account, room_jid)
|
||||||
gajim.interface.instances[account]['join_gc'] = \
|
|
||||||
JoinGroupchatWindow(account, room_jid, nick)
|
|
||||||
else:
|
else:
|
||||||
gajim.interface.join_gc_room(account, room_jid, nick, password)
|
gajim.interface.join_gc_room(account, room_jid, nick, password)
|
||||||
|
|
||||||
from gajim.common import app
|
from gajim.common import app
|
||||||
from gajim.common import helpers
|
from gajim.common import helpers
|
||||||
from time import time
|
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 import GajimPlugin
|
||||||
from gajim.plugins.helpers import log_calls, log
|
from gajim.plugins.helpers import log_calls, log
|
||||||
|
|
Loading…
Add table
Reference in a new issue