diff --git a/gajim/app_actions.py b/gajim/app_actions.py
index 8b7ae5cb3..cca92058d 100644
--- a/gajim/app_actions.py
+++ b/gajim/app_actions.py
@@ -18,14 +18,15 @@
## along with Gajim. If not, see .
##
+import sys
+import os
+
+from gi.repository import Gtk
+
from gajim.common import app
from gajim.common import helpers
from gajim.common.app import interface
from gajim.common.exceptions import GajimGeneralException
-from gi.repository import Gtk
-import sys
-import os
-
from gajim import config
from gajim import dialogs
from gajim import features_window
@@ -116,13 +117,10 @@ class AppActions():
'You cannot join a group chat while you are invisible'))
return
if 'join_gc' in interface.instances[account]:
- interface.instances[account]['join_gc'].window.present()
+ interface.instances[account]['join_gc'].present()
else:
- try:
- interface.instances[account]['join_gc'] = \
- dialogs.JoinGroupchatWindow(account)
- except GajimGeneralException:
- pass
+ interface.instances[account]['join_gc'] = \
+ dialogs.JoinGroupchatWindow(account, None)
def on_add_contact(self, action, param):
dialogs.AddNewContactWindow(param.get_string())
diff --git a/gajim/chat_control.py b/gajim/chat_control.py
index 9442e19a2..a677fc5cf 100644
--- a/gajim/chat_control.py
+++ b/gajim/chat_control.py
@@ -1601,15 +1601,13 @@ class ChatControl(ChatControlBase):
self._add_info_bar_message(markup, [b], file_props, Gtk.MessageType.ERROR)
def _on_accept_gc_invitation(self, widget, event):
- try:
- if event.is_continued:
- app.interface.join_gc_room(self.account, event.room_jid,
- app.nicks[self.account], event.password,
- is_continued=True)
- else:
- dialogs.JoinGroupchatWindow(self.account, event.room_jid)
- except GajimGeneralException:
- pass
+ if event.is_continued:
+ app.interface.join_gc_room(self.account, event.room_jid,
+ app.nicks[self.account], event.password,
+ is_continued=True)
+ else:
+ app.interface.join_gc_minimal(self.account, event.room_jid)
+
app.events.remove_events(self.account, self.contact.jid, event=event)
def _on_cancel_gc_invitation(self, widget, event):
diff --git a/gajim/command_system/implementation/standard.py b/gajim/command_system/implementation/standard.py
index 0d96cc30f..059be9fae 100644
--- a/gajim/command_system/implementation/standard.py
+++ b/gajim/command_system/implementation/standard.py
@@ -296,21 +296,12 @@ class StandardGroupChatCommands(CommandContainer):
'room_jid': self.room_jid}
@command(raw=True, empty=True)
- @doc(_("Join a group chat given by a jid, optionally using given nickname"))
- def join(self, jid, nick):
- if not nick:
- nick = self.nick
-
+ @doc(_("Join a group chat given by a jid"))
+ def join(self, jid):
if '@' not in jid:
jid = jid + '@' + app.get_server_from_jid(self.room_jid)
- try:
- 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
+ app.interface.join_gc_minimal(self.account, room_jid=jid)
@command('part', 'close', raw=True, empty=True)
@doc(_("Leave the groupchat, optionally giving a reason, and close tab or window"))
diff --git a/gajim/common/app.py b/gajim/common/app.py
index 010117a36..0a2e60632 100644
--- a/gajim/common/app.py
+++ b/gajim/common/app.py
@@ -33,6 +33,7 @@ import logging
import locale
import uuid
from distutils.version import LooseVersion as V
+from collections import namedtuple
import gi
import nbxmpp
import hashlib
@@ -81,6 +82,8 @@ PLUGINS_DIRS = [gajimpaths['PLUGINS_BASE'],
PLUGINS_CONFIG_DIR = gajimpaths['PLUGINS_CONFIG_DIR']
MY_CERT_DIR = gajimpaths['MY_CERT']
+RecentGroupchat = namedtuple('RecentGroupchat', ['room', 'server', 'nickname'])
+
try:
LANG = locale.getdefaultlocale()[0] # en_US, fr_FR, el_GR etc..
except (ValueError, locale.Error):
@@ -373,6 +376,16 @@ def get_number_of_connected_accounts(accounts_list = None):
connected_accounts = connected_accounts + 1
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):
if account not in connections:
return False
@@ -388,6 +401,11 @@ def zeroconf_is_connected():
return account_is_connected(ZEROCONF_ACC_NAME) and \
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():
"""
Return the number of the accounts that are SSL/TLS connected
@@ -495,6 +513,34 @@ def get_name_from_jid(account, jid):
actor = jid
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):
"""
Return the priority an account must have
diff --git a/gajim/common/caps_cache.py b/gajim/common/caps_cache.py
index 957633f7d..b0975067c 100644
--- a/gajim/common/caps_cache.py
+++ b/gajim/common/caps_cache.py
@@ -472,6 +472,10 @@ class MucCapsCache:
if child.getNamespace() == nbxmpp.NS_DATA:
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)
def is_cached(self, jid):
diff --git a/gajim/common/config.py b/gajim/common/config.py
index 258df8afe..e2148448c 100644
--- a/gajim/common/config.py
+++ b/gajim/common/config.py
@@ -174,7 +174,6 @@ class Config:
'history_window_x-position': [ opt_int, 0 ],
'history_window_y-position': [ opt_int, 0 ],
'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') ],
'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') ],
@@ -409,6 +408,7 @@ class Config:
'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.')],
'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': ({
'message': [ opt_str, '' ],
diff --git a/gajim/common/connection_handlers.py b/gajim/common/connection_handlers.py
index 01180fc98..5ac99fc48 100644
--- a/gajim/common/connection_handlers.py
+++ b/gajim/common/connection_handlers.py
@@ -98,6 +98,9 @@ class ConnectionDisco:
self.disco_info_ids.append(id_)
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)
self.connection.SendAndCallForResponse(
disco_info, self.received_muc_info, {'callback': callback})
diff --git a/gajim/conversation_textview.py b/gajim/conversation_textview.py
index 721306d93..f1968f88d 100644
--- a/gajim/conversation_textview.py
+++ b/gajim/conversation_textview.py
@@ -689,15 +689,9 @@ class ConversationTextview(GObject.GObject):
app.interface.new_chat_from_jid(self.account, jid)
def on_join_group_chat_menuitem_activate(self, widget, room_jid):
- if 'join_gc' in app.interface.instances[self.account]:
- instance = app.interface.instances[self.account]['join_gc']
- instance.xml.get_object('room_jid_entry').set_text(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
+ # Remove ?join
+ room_jid = room_jid.split('?')[0]
+ app.interface.join_gc_minimal(self.account, room_jid)
def on_add_to_roster_activate(self, widget, jid):
dialogs.AddNewContactWindow(self.account, jid)
@@ -805,7 +799,7 @@ class ConversationTextview(GObject.GObject):
if '?' in word:
(jid, action) = word.split('?')
if action == 'join':
- self.on_join_group_chat_menuitem_activate(None, jid)
+ app.interface.join_gc_minimal(None, jid)
else:
self.on_start_chat_activate(None, jid)
else:
diff --git a/gajim/data/gui/join_groupchat_window.ui b/gajim/data/gui/join_groupchat_window.ui
new file mode 100644
index 000000000..9aff6a87b
--- /dev/null
+++ b/gajim/data/gui/join_groupchat_window.ui
@@ -0,0 +1,340 @@
+
+
+
+
+
+
+
diff --git a/gajim/data/style/gajim.css b/gajim/data/style/gajim.css
index 88a8335cd..a84354402 100644
--- a/gajim/data/style/gajim.css
+++ b/gajim/data/style/gajim.css
@@ -86,4 +86,6 @@ popover#EmoticonPopover flowboxchild { padding-top: 5px; padding-bottom: 5px; }
background-color: @theme_unfocused_bg_color;
color: @theme_text_color; }
+/* Text style */
+.bold16 { font-size: 16px; font-weight: bold; }
diff --git a/gajim/dialogs.py b/gajim/dialogs.py
index 5a9cd867c..49d1c657b 100644
--- a/gajim/dialogs.py
+++ b/gajim/dialogs.py
@@ -61,6 +61,7 @@ from gajim.common import app
from gajim.common import helpers
from gajim.common import i18n
from gajim.common import dataforms
+from gajim.common.caps_cache import muc_caps_cache
from gajim.common.exceptions import GajimGeneralException
from gajim.common.connection_handlers_events import MessageOutgoingEvent
@@ -2350,198 +2351,233 @@ class SubscriptionRequestWindow:
gtkgui_helpers.popup_emoticons_under_button(menu, widget,
self.window.get_window())
-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
+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'))
- 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._empty_required_widgets = []
-
- 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.password = password
self.requested_jid = None
- app.ged.register_event_handler('agent-info-received', ged.GUI1,
- self._nec_agent_info_received)
- app.ged.register_event_handler('agent-info-error-received', ged.GUI1,
- self._nec_agent_info_error_received)
+ self.room_jid = room_jid
+ self.account = account
+ self.minimal_mode = room_jid is not None
- self.window.show_all()
+ 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']
- def on_join_groupchat_window_destroy(self, widget):
- """
- Close window
- """
- app.ged.remove_event_handler('agent-info-received', ged.GUI1,
- self._nec_agent_info_received)
- app.ged.register_event_handler('agent-info-error-received', ged.GUI1,
- 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']
+ minimal_widgets = ['jid_label']
- def on_join_groupchat_window_key_press_event(self, widget, event):
- if event.keyval == Gdk.KEY_Escape: # ESCAPE
- widget.destroy()
+ 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))
- 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)
+ self.add(self.grid)
+
+ if os.environ.get('GTK_CSD', '1') == '1':
+ self.set_titlebar(self.headerbar)
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()
+ self.button_box.show()
- 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)
+ # 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)
- def _set_room_jid(self, full_jid):
- room_jid, nick = app.get_room_and_nick_from_fjid(full_jid)
+ 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,
+ self._nec_agent_info_received)
+ app.ged.register_event_handler('agent-info-error-received', ged.GUI1,
+ self._nec_agent_info_error_received)
+
+ # Show account combobox if there is more than one account
+ if len(connected_accounts) > 1:
+ self.account_combo.show()
+ self.account_label.show()
+
+ # Select first account
+ self.account_combo.set_active(0)
+ 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_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)
+ self.room_entry.set_text(room)
+ self.server_combo.get_child().set_text(server)
- 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 _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)
- def on_browse_rooms_button_clicked(self, widget):
- server = self.server_comboboxtext.get_child().get_text()
+ 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,
+ self._nec_agent_info_received)
+ app.ged.remove_event_handler('agent-info-error-received', ged.GUI1,
+ self._nec_agent_info_error_received)
+
+ def _on_search_clicked(self, widget):
+ server = self.server_combo.get_active_text()
self.requested_jid = server
app.connections[self.account].discoverInfo(server)
@@ -2551,9 +2587,9 @@ class JoinGroupchatWindow:
if obj.jid != self.requested_jid:
return
self.requested_jid = None
- window = app.interface.instances[self.account]['join_gc'].window
- ErrorDialog(_('Wrong server'), _('%s is not a groupchat server') % \
- obj.jid, transient_for=window)
+ ErrorDialog(_('Wrong server'),
+ _('%s is not a groupchat server') % obj.jid,
+ transient_for=self)
def _nec_agent_info_received(self, obj):
if obj.conn.name != self.account:
@@ -2562,9 +2598,9 @@ class JoinGroupchatWindow:
return
self.requested_jid = None
if nbxmpp.NS_MUC not in obj.features:
- window = app.interface.instances[self.account]['join_gc'].window
- ErrorDialog(_('Wrong server'), _('%s is not a groupchat server') % \
- obj.jid, transient_for=window)
+ ErrorDialog(_('Wrong server'),
+ _('%s is not a groupchat server') % obj.jid,
+ transient_for=self)
return
if obj.jid in app.interface.instances[self.account]['disco']:
app.interface.instances[self.account]['disco'][obj.jid].window.\
@@ -2572,10 +2608,11 @@ class JoinGroupchatWindow:
else:
try:
# Object will add itself to the window dict
- import disco
- disco.ServiceDiscoveryWindow(self.account, obj.jid,
+ from gajim.disco import ServiceDiscoveryWindow
+ ServiceDiscoveryWindow(
+ self.account, obj.jid,
initial_identities=[{'category': 'conference',
- 'type': 'text'}])
+ 'type': 'text'}])
except GajimGeneralException:
pass
@@ -4389,16 +4426,13 @@ class InvitationReceivedDialog:
sectext += '\n\n' + _('Do you want to accept the invitation?')
def on_yes(checked, text):
- try:
- if self.is_continued:
- app.interface.join_gc_room(self.account, self.room_jid,
- app.nicks[self.account], self.password,
- is_continued=True)
- else:
- JoinGroupchatWindow(self.account, self.room_jid,
- password=self.password)
- except GajimGeneralException:
- pass
+ if self.is_continued:
+ app.interface.join_gc_room(self.account, self.room_jid,
+ app.nicks[self.account], self.password,
+ is_continued=True)
+ else:
+ app.interface.join_gc_minimal(
+ self.account, self.room_jid, password=self.password)
def on_no(text):
app.connections[account].decline_invitation(self.room_jid,
@@ -4741,7 +4775,7 @@ class TransformChatToMUC:
if 'jabber' in app.connections[account].muc_jid:
server_list.append(app.connections[account].muc_jid['jabber'])
# 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:
server = app.get_server_from_jid(g)
if server not in server_list and not server.startswith('irc'):
diff --git a/gajim/disco.py b/gajim/disco.py
index 536e6ee74..4d43f1d2b 100644
--- a/gajim/disco.py
+++ b/gajim/disco.py
@@ -1400,13 +1400,7 @@ class ToplevelAgentBrowser(AgentBrowser):
if not iter_:
return
service = model[iter_][0]
- if 'join_gc' not in app.interface.instances[self.account]:
- try:
- dialogs.JoinGroupchatWindow(self.account, service)
- except GajimGeneralException:
- pass
- else:
- app.interface.instances[self.account]['join_gc'].window.present()
+ app.interface.join_gc_minimal(self.account, service)
def update_actions(self):
if self.execute_button:
@@ -1810,14 +1804,11 @@ class MucBrowser(AgentBrowser):
return
service = model[iter_][0]
if 'join_gc' not in app.interface.instances[self.account]:
- try:
- dialogs.JoinGroupchatWindow(self.account, service)
- except GajimGeneralException:
- pass
+ app.interface.join_gc_minimal(self.account, service)
else:
- app.interface.instances[self.account]['join_gc']._set_room_jid(
- service)
- app.interface.instances[self.account]['join_gc'].window.present()
+ app.interface.instances[self.account]['join_gc'].set_room(service)
+ app.interface.instances[self.account]['join_gc'].present()
+ self.window.destroy()
def update_actions(self):
sens = self.window.services_treeview.get_selection().count_selected_rows()
diff --git a/gajim/gajim.py b/gajim/gajim.py
index 9801d66a5..dc023a802 100644
--- a/gajim/gajim.py
+++ b/gajim/gajim.py
@@ -60,7 +60,8 @@ class GajimApplication(Gtk.Application):
'''Main class handling activation and command line.'''
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,
GLib.OptionArg.NONE,
@@ -89,13 +90,11 @@ class GajimApplication(Gtk.Application):
self.add_main_option('warnings', ord('w'), GLib.OptionFlags.NONE,
GLib.OptionArg.NONE,
_('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('startup', self._startup)
self.connect('activate', self._activate)
+ self.connect('open', self._open)
self.profile = ''
self.config_path = None
@@ -235,6 +234,15 @@ class GajimApplication(Gtk.Application):
from gajim import gui_menu_builder
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)
+
def do_shutdown(self, *args):
Gtk.Application.do_shutdown(self)
# Shutdown GUI and save config
@@ -274,10 +282,6 @@ class GajimApplication(Gtk.Application):
logging_helpers.set_loglevels(loglevel)
if options.contains('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
def show_warnings(self):
diff --git a/gajim/gui_interface.py b/gajim/gui_interface.py
index faab21f9b..2ad82a292 100644
--- a/gajim/gui_interface.py
+++ b/gajim/gui_interface.py
@@ -101,6 +101,7 @@ from gajim import profile_window
from gajim import config
from threading import Thread
from gajim.common import ged
+from gajim.common.caps_cache import muc_caps_cache
from gajim.common.configpaths import gajimpaths
config_filename = gajimpaths['CONFIG_FILE']
@@ -1757,6 +1758,49 @@ class Interface:
tv = ctrl.conv_textview
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
################################################################################
@@ -1953,8 +1997,6 @@ class Interface:
win.set_active_tab(gc_ctrl)
else:
self.roster.on_groupchat_maximized(None, room_jid, account)
- dialogs.ErrorDialog(_('You are already in group chat %s') % \
- room_jid)
return
invisible_show = app.SHOW_LIST.index('invisible')
@@ -2130,6 +2172,7 @@ class Interface:
### Other Methods
################################################################################
+
@staticmethod
def change_awn_icon_status(status):
if not dbus_support.supported:
@@ -2454,7 +2497,7 @@ class Interface:
self.roster.add_groupchat(jid, account)
def add_gc_bookmark(self, account, name, jid, autojoin, minimize, password,
- nick):
+ nick):
"""
Add a bookmark for this account, sorted in bookmark list
"""
@@ -2471,10 +2514,6 @@ class Interface:
# check for duplicate entry and respect alpha order
for bookmark in app.connections[account].bookmarks:
if bookmark['jid'] == bm['jid']:
- dialogs.ErrorDialog(
- _('Bookmark already set'),
- _('Group Chat "%s" is already in your bookmarks.') % \
- bm['jid'])
return
if bookmark['name'] > bm['name']:
place_found = True
@@ -2486,10 +2525,6 @@ class Interface:
app.connections[account].bookmarks.append(bm)
app.connections[account].store_bookmarks()
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?
def is_pm_contact(self, fjid, account):
diff --git a/gajim/htmltextview.py b/gajim/htmltextview.py
index a5eeb2ff4..d05d9a4a9 100644
--- a/gajim/htmltextview.py
+++ b/gajim/htmltextview.py
@@ -915,10 +915,7 @@ class HtmlTextView(Gtk.TextView):
# app.interface.new_chat_from_jid(self.account, jid)
def on_join_group_chat_menuitem_activate(self, widget, room_jid):
- try:
- dialogs.JoinGroupchatWindow(room_jid=room_jid)
- except GajimGeneralException:
- pass
+ dialogs.JoinGroupchatWindow(None, room_jid)
def on_add_to_roster_activate(self, widget, jid):
dialogs.AddNewContactWindow(self.account, jid)
diff --git a/gajim/remote_control.py b/gajim/remote_control.py
index 6ca4651aa..0e3abcfa8 100644
--- a/gajim/remote_control.py
+++ b/gajim/remote_control.py
@@ -908,8 +908,6 @@ class SignalObject(dbus.service.Object):
return
if not nick:
- nick = ''
- app.interface.instances[account]['join_gc'] = \
- JoinGroupchatWindow(account, room_jid, nick)
+ app.interface.join_gc_minimal(account, room_jid)
else:
app.interface.join_gc_room(account, room_jid, nick, password)
diff --git a/gajim/roster_window.py b/gajim/roster_window.py
index 4cf496d4a..d11f29305 100644
--- a/gajim/roster_window.py
+++ b/gajim/roster_window.py
@@ -3091,15 +3091,11 @@ class RosterWindow:
if app.connections[account].muc_jid[type_]:
# create the room on this muc server
if 'join_gc' in app.interface.instances[account]:
- app.interface.instances[account]['join_gc'].window.\
- destroy()
- try:
+ app.interface.instances[account]['join_gc'].destroy()
+ else:
app.interface.instances[account]['join_gc'] = \
- dialogs.JoinGroupchatWindow(account,
- app.connections[account].muc_jid[type_],
- automatic = {'invities': jid_list})
- except GajimGeneralException:
- continue
+ dialogs.JoinGroupchatWindow(
+ account, None, automatic={'invities': jid_list})
break
def on_invite_to_room(self, widget, list_, room_jid, room_account,
@@ -3676,13 +3672,10 @@ class RosterWindow:
'invisible'))
return
if 'join_gc' in app.interface.instances[account]:
- app.interface.instances[account]['join_gc'].window.present()
+ app.interface.instances[account]['join_gc'].present()
else:
- try:
- app.interface.instances[account]['join_gc'] = \
- dialogs.JoinGroupchatWindow(account)
- except GajimGeneralException:
- pass
+ app.interface.instances[account]['join_gc'] = \
+ dialogs.JoinGroupchatWindow(account, None)
def on_new_chat_menuitem_activate(self, widget, account):
dialogs.NewChatDialog(account)
diff --git a/plugins/dbus_plugin/plugin.py b/plugins/dbus_plugin/plugin.py
index 7e1ffd353..074b9326f 100644
--- a/plugins/dbus_plugin/plugin.py
+++ b/plugins/dbus_plugin/plugin.py
@@ -651,9 +651,7 @@ if dbus_support.supported:
if not account:
return
if not nick:
- nick = ''
- gajim.interface.instances[account]['join_gc'] = \
- JoinGroupchatWindow(account, room_jid, nick)
+ gajim.interface.join_gc_minimal(account, room_jid)
else:
gajim.interface.join_gc_room(account, room_jid, nick, password)