Refactor UserNickname and UserMood

- Use IconTheme for mood icons
- Simplify modules because nbxmpp handles more stuff
This commit is contained in:
Philipp Hörist 2019-01-30 20:23:16 +01:00
parent 8e336311cc
commit be95b04007
101 changed files with 243 additions and 167 deletions

View file

@ -47,6 +47,7 @@ from gajim.common.contacts import GC_Contact
from gajim.common.const import AvatarSize
from gajim.common.const import KindConstant
from gajim.common.const import Chatstate
from gajim.common.const import PEPEventType
from gajim import gtkgui_helpers
from gajim import gui_menu_builder
@ -57,6 +58,8 @@ from gajim.gtk.dialogs import ConfirmationDialog
from gajim.gtk.add_contact import AddNewContactWindow
from gajim.gtk.util import get_icon_name
from gajim.gtk.util import get_cursor
from gajim.gtk.util import ensure_proper_control
from gajim.gtk.util import format_mood
from gajim.command_system.implementation.hosts import ChatCommands
from gajim.command_system.framework import CommandHost # pylint: disable=unused-import
@ -128,7 +131,6 @@ class ChatControl(ChatControlBase):
self.update_toolbar()
self._pep_images = {}
self._pep_images['mood'] = self.xml.get_object('mood_image')
self._pep_images['activity'] = self.xml.get_object('activity_image')
self._pep_images['tune'] = self.xml.get_object('tune_image')
self._pep_images['geoloc'] = self.xml.get_object('location_image')
@ -227,6 +229,10 @@ class ChatControl(ChatControlBase):
app.ged.register_event_handler('pep-received', ged.GUI1,
self._nec_pep_received)
app.ged.register_event_handler('nickname-received', ged.GUI1,
self._on_nickname_received)
app.ged.register_event_handler('mood-received', ged.GUI1,
self._on_mood_received)
if self.TYPE_ID == message_control.TYPE_CHAT:
# Dont connect this when PrivateChatControl is used
app.ged.register_event_handler('update-roster-avatar', ged.GUI1,
@ -409,6 +415,7 @@ class ChatControl(ChatControlBase):
def update_all_pep_types(self):
for pep_type in self._pep_images:
self.update_pep(pep_type)
self._update_pep(PEPEventType.MOOD)
def update_pep(self, pep_type):
if isinstance(self.contact, GC_Contact):
@ -434,12 +441,36 @@ class ChatControl(ChatControlBase):
if obj.jid != self.contact.jid:
return
if obj.pep_type == 'nick':
self.update_ui()
self.parent_win.redraw_tab(self)
self.parent_win.show_title()
else:
self.update_pep(obj.pep_type)
self.update_pep(obj.pep_type)
def _update_pep(self, type_):
image = self._get_pep_widget(type_)
data = self.contact.pep.get(type_)
if data is None:
image.hide()
return
if type_ == PEPEventType.MOOD:
icon = 'mood-%s' % data.mood
formated_text = format_mood(*data)
image.set_from_icon_name(icon, Gtk.IconSize.MENU)
image.set_tooltip_markup(formated_text)
image.show()
def _get_pep_widget(self, type_):
if type_ == PEPEventType.MOOD:
return self.xml.get_object('mood_image')
@ensure_proper_control
def _on_mood_received(self, _event):
self._update_pep(PEPEventType.MOOD)
@ensure_proper_control
def _on_nickname_received(self, _event):
self.update_ui()
self.parent_win.redraw_tab(self)
self.parent_win.show_title()
def _update_jingle(self, jingle_type):
if jingle_type not in ('audio', 'video'):
@ -1051,6 +1082,10 @@ class ChatControl(ChatControlBase):
app.ged.remove_event_handler('pep-received', ged.GUI1,
self._nec_pep_received)
app.ged.remove_event_handler('nickname-received', ged.GUI1,
self._on_nickname_received)
app.ged.remove_event_handler('mood-received', ged.GUI1,
self._on_mood_received)
if self.TYPE_ID == message_control.TYPE_CHAT:
app.ged.remove_event_handler('update-roster-avatar', ged.GUI1,
self._nec_update_avatar)

View file

@ -221,8 +221,6 @@ class ConfigPaths:
'emoticons', PathLocation.DATA, PathType.FOLDER_OPTIONAL),
('MY_ICONSETS',
'iconsets', PathLocation.DATA, PathType.FOLDER_OPTIONAL),
('MY_MOOD_ICONSETS',
'moods', PathLocation.DATA, PathType.FOLDER_OPTIONAL),
('MY_ACTIVITY_ICONSETS',
'activities', PathLocation.DATA, PathType.FOLDER_OPTIONAL),

View file

@ -1631,6 +1631,7 @@ class Connection(CommonConnection, ConnectionHandlers):
# Inform GUI we just signed in
app.nec.push_incoming_event(NetworkEvent('signed-in', conn=self))
modules.send_stored_publish(self.name)
self.get_module('PEP').send_stored_publish()
self.continue_connect_info = None

View file

@ -1098,13 +1098,6 @@ def get_current_show(account):
status = app.connections[account].connected
return app.SHOW_LIST[status]
def get_mood_iconset_path(iconset):
if os.path.isdir(os.path.join(configpaths.get('DATA'), 'moods', iconset)):
return os.path.join(configpaths.get('DATA'), 'moods', iconset)
if os.path.isdir(
os.path.join(configpaths.get('MY_MOOD_ICONSETS'), iconset)):
return os.path.join(configpaths.get('MY_MOOD_ICONSETS'), iconset)
def get_activity_iconset_path(iconset):
if os.path.isdir(os.path.join(configpaths.get('DATA'), 'activities', iconset)):
return os.path.join(configpaths.get('DATA'), 'activities', iconset)

View file

@ -34,6 +34,8 @@ ZEROCONF_MODULES = ['iq',
_imported_modules = [] # type: List[tuple]
_modules = {} # type: Dict[str, Dict[str, Any]]
_store_publish_modules = [
'UserMood'] # type: List[str]
for file in Path(__file__).parent.iterdir():
if file.stem == '__init__':
@ -112,6 +114,11 @@ def unregister_single(con: ConnectionT, name: str) -> None:
del _modules[con.name][name]
def send_stored_publish(account: str) -> None:
for name in _store_publish_modules:
_modules[account][name].send_stored_publish()
def get(account: str, name: str) -> Any:
try:
return _modules[account][name]

View file

@ -20,6 +20,9 @@ import logging
from functools import partial
from unittest.mock import Mock
import nbxmpp
from nbxmpp.structs import StanzaHandler
from gajim.common import app
log = logging.getLogger('gajim.c.m.base')
@ -34,6 +37,7 @@ class BaseModule:
self._con = con
self._account = con.name
self._nbxmpp_callbacks = {} # type: Dict[str, Any]
self._stored_publish = None # type: Callable
self.handlers = [] # type: List[str]
def __getattr__(self, key):
@ -46,8 +50,10 @@ class BaseModule:
module = self._con.connection.get_module(self._nbxmpp_extends)
return partial(getattr(module, key),
callback=self._nbxmpp_callbacks.get(key))
callback = self._nbxmpp_callbacks.get(key)
if callback is None:
return getattr(module, key)
return partial(getattr(module, key), callback=callback)
def _nbxmpp(self, module_name=None):
if not app.account_is_connected(self._account):
@ -61,3 +67,16 @@ class BaseModule:
def _register_callback(self, method, callback):
self._nbxmpp_callbacks[method] = callback
def _register_pubsub_handler(self, callback):
handler = StanzaHandler(name='message',
callback=callback,
ns=nbxmpp.NS_PUBSUB_EVENT,
priority=49)
self.handlers.append(handler)
def send_stored_publish(self):
if self._stored_publish is None:
return
log.info('Send stored publish')
self._stored_publish()

View file

@ -55,12 +55,11 @@ class Message:
]
# XEPs for which this message module should not be executed
self._message_namespaces = set([nbxmpp.NS_PUBSUB_EVENT,
nbxmpp.NS_ROSTERX,
self._message_namespaces = set([nbxmpp.NS_ROSTERX,
nbxmpp.NS_IBB])
def _message_received(self, _con, stanza, properties):
if properties.is_mam_message:
if properties.is_mam_message or properties.is_pubsub_event:
return
# Check if a child of the message contains any
# namespaces that we handle in other modules.

View file

@ -6,94 +6,69 @@
#
# Gajim is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
# XEP-0107: User Mood
from typing import Any
from typing import Dict
from typing import List # pylint: disable=unused-import
from typing import Optional
from typing import Tuple
import logging
import nbxmpp
from gi.repository import GLib
from gajim.common.const import PEPEventType, MOODS
from gajim.common.exceptions import StanzaMalformed
from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData
from gajim.common import app
from gajim.common.nec import NetworkEvent
from gajim.common.modules.base import BaseModule
from gajim.common.modules.util import event_node
from gajim.common.modules.util import store_publish
from gajim.common.const import PEPEventType
log = logging.getLogger('gajim.c.m.user_mood')
class UserMoodData(AbstractPEPData):
class UserMood(BaseModule):
type_ = PEPEventType.MOOD
_nbxmpp_extends = 'Mood'
_nbxmpp_methods = [
'set_mood',
]
def as_markup_text(self) -> str:
if self.data is None:
return ''
mood = self._translate_mood(self.data['mood'])
markuptext = '<b>%s</b>' % GLib.markup_escape_text(mood)
if 'text' in self.data:
text = self.data['text']
markuptext += ' (%s)' % GLib.markup_escape_text(text)
return markuptext
def __init__(self, con):
BaseModule.__init__(self, con)
self._register_pubsub_handler(self._mood_received)
@staticmethod
def _translate_mood(mood: str) -> str:
if mood in MOODS:
return MOODS[mood]
return mood
class UserMood(AbstractPEPModule):
name = 'mood'
namespace = nbxmpp.NS_MOOD
pep_class = UserMoodData
store_publish = True
_log = log
def _extract_info(self, item: nbxmpp.Node) -> Optional[Dict[str, str]]:
mood_dict = {}
mood_tag = item.getTag('mood', namespace=nbxmpp.NS_MOOD)
if mood_tag is None:
raise StanzaMalformed('No mood node')
if not mood_tag.getChildren():
return None
for child in mood_tag.getChildren():
name = child.getName().strip()
if name == 'text':
mood_dict['text'] = child.getData()
@event_node(nbxmpp.NS_MOOD)
def _mood_received(self, _con, _stanza, properties):
data = properties.pubsub_event.data
for contact in app.contacts.get_contacts(self._account,
str(properties.jid)):
if data.mood is not None:
contact.pep[PEPEventType.MOOD] = data
else:
mood_dict['mood'] = name
contact.pep.pop(PEPEventType.MOOD, None)
if 'mood' not in mood_dict:
raise StanzaMalformed('No mood value found')
return mood_dict
if properties.is_self_message:
if data.mood is not None:
self._con.pep[PEPEventType.MOOD] = data
else:
self._con.pep.pop(PEPEventType.MOOD, None)
def _build_node(self, data: Optional[Tuple[str, str]]) -> nbxmpp.Node:
item = nbxmpp.Node('mood', {'xmlns': nbxmpp.NS_MOOD})
if data is None:
return item
app.nec.push_incoming_event(
NetworkEvent('mood-received',
account=self._account,
jid=properties.jid.getBare(),
mood=data,
is_self_message=properties.is_self_message))
mood, text = data
if not mood:
return item
item.addChild(mood)
if text:
item.addChild('text', payload=text)
return item
@store_publish
def set_mood(self, mood):
log.info('Send %s', mood)
self._nbxmpp('Mood').set_mood(mood)
def get_instance(*args: Any, **kwargs: Any) -> Tuple[UserMood, str]:

View file

@ -6,17 +6,15 @@
#
# Gajim is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
# XEP-0172: User Nickname
from typing import Any
from typing import List # pylint: disable=unused-import
from typing import Optional
from typing import Tuple
import logging
@ -24,56 +22,41 @@ import logging
import nbxmpp
from gajim.common import app
from gajim.common.const import PEPEventType
from gajim.common.exceptions import StanzaMalformed
from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData
from gajim.common.nec import NetworkEvent
from gajim.common.modules.base import BaseModule
from gajim.common.modules.util import event_node
log = logging.getLogger('gajim.c.m.user_nickname')
class UserNicknameData(AbstractPEPData):
class UserNickname(BaseModule):
type_ = PEPEventType.NICKNAME
_nbxmpp_extends = 'Nickname'
_nbxmpp_methods = [
'set_nickname',
]
def get_nick(self) -> str:
return self.data or ''
def __init__(self, con):
BaseModule.__init__(self, con)
self._register_pubsub_handler(self._nickname_received)
@event_node(nbxmpp.NS_NICK)
def _nickname_received(self, _con, _stanza, properties):
nick = properties.pubsub_event.data
if properties.self_message:
if nick is None:
nick = app.config.get_per('accounts', self._account, 'name')
app.nicks[self._account] = nick
class UserNickname(AbstractPEPModule):
for contact in app.contacts.get_contacts(self._account,
str(properties.jid)):
contact.contact_name = nick
name = 'nick'
namespace = nbxmpp.NS_NICK
pep_class = UserNicknameData
store_publish = True
_log = log
def _extract_info(self, item: nbxmpp.Node) -> Optional[str]:
nick = ''
child = item.getTag('nick', namespace=nbxmpp.NS_NICK)
if child is None:
raise StanzaMalformed('No nick node')
nick = child.getData()
return nick or None
def _build_node(self, data: Optional[str]) -> Optional[nbxmpp.Node]:
item = nbxmpp.Node('nick', {'xmlns': nbxmpp.NS_NICK})
if data is not None:
item.addData(data)
return item
def _notification_received(self,
jid: nbxmpp.JID,
user_pep: UserNicknameData) -> None:
for contact in app.contacts.get_contacts(self._account, str(jid)):
contact.contact_name = user_pep.get_nick()
if jid == self._con.get_own_jid().getStripped():
if user_pep:
app.nicks[self._account] = user_pep.get_nick()
else:
app.nicks[self._account] = app.config.get_per(
'accounts', self._account, 'name')
app.nec.push_incoming_event(
NetworkEvent('nickname-received',
account=self._account,
jid=properties.jid.getBare(),
nickname=nick))
def parse_nickname(stanza: nbxmpp.Node) -> str:

View file

@ -16,6 +16,11 @@
from typing import Union
from functools import wraps
from functools import partial
from gajim.common import app
def from_xs_boolean(value: Union[str, bool]) -> bool:
if isinstance(value, bool):
@ -44,3 +49,25 @@ def to_xs_boolean(value: Union[bool, None]) -> str:
raise ValueError(
'Cant convert %s to xs:boolean' % value)
def event_node(node):
def event_node_decorator(func):
@wraps(func)
def func_wrapper(self, _con, _stanza, properties):
if properties.pubsub_event.node != node:
return
func(self, _con, _stanza, properties)
return func_wrapper
return event_node_decorator
def store_publish(func):
@wraps(func)
def func_wrapper(self, *args, **kwargs):
if not app.account_is_connected(self._account):
self._stored_publish = partial(func, self, *args, **kwargs)
return
return func(self, *args, **kwargs)
return func_wrapper

View file

Before

Width:  |  Height:  |  Size: 984 B

After

Width:  |  Height:  |  Size: 984 B

View file

Before

Width:  |  Height:  |  Size: 966 B

After

Width:  |  Height:  |  Size: 966 B

View file

Before

Width:  |  Height:  |  Size: 989 B

After

Width:  |  Height:  |  Size: 989 B

View file

Before

Width:  |  Height:  |  Size: 943 B

After

Width:  |  Height:  |  Size: 943 B

View file

Before

Width:  |  Height:  |  Size: 924 B

After

Width:  |  Height:  |  Size: 924 B

View file

Before

Width:  |  Height:  |  Size: 949 B

After

Width:  |  Height:  |  Size: 949 B

View file

Before

Width:  |  Height:  |  Size: 956 B

After

Width:  |  Height:  |  Size: 956 B

View file

Before

Width:  |  Height:  |  Size: 942 B

After

Width:  |  Height:  |  Size: 942 B

View file

Before

Width:  |  Height:  |  Size: 934 B

After

Width:  |  Height:  |  Size: 934 B

View file

Before

Width:  |  Height:  |  Size: 931 B

After

Width:  |  Height:  |  Size: 931 B

View file

Before

Width:  |  Height:  |  Size: 918 B

After

Width:  |  Height:  |  Size: 918 B

View file

Before

Width:  |  Height:  |  Size: 922 B

After

Width:  |  Height:  |  Size: 922 B

View file

Before

Width:  |  Height:  |  Size: 996 B

After

Width:  |  Height:  |  Size: 996 B

View file

Before

Width:  |  Height:  |  Size: 913 B

After

Width:  |  Height:  |  Size: 913 B

View file

Before

Width:  |  Height:  |  Size: 951 B

After

Width:  |  Height:  |  Size: 951 B

View file

Before

Width:  |  Height:  |  Size: 907 B

After

Width:  |  Height:  |  Size: 907 B

View file

Before

Width:  |  Height:  |  Size: 886 B

After

Width:  |  Height:  |  Size: 886 B

View file

Before

Width:  |  Height:  |  Size: 939 B

After

Width:  |  Height:  |  Size: 939 B

View file

Before

Width:  |  Height:  |  Size: 981 B

After

Width:  |  Height:  |  Size: 981 B

View file

Before

Width:  |  Height:  |  Size: 916 B

After

Width:  |  Height:  |  Size: 916 B

View file

Before

Width:  |  Height:  |  Size: 944 B

After

Width:  |  Height:  |  Size: 944 B

View file

Before

Width:  |  Height:  |  Size: 886 B

After

Width:  |  Height:  |  Size: 886 B

View file

Before

Width:  |  Height:  |  Size: 1,001 B

After

Width:  |  Height:  |  Size: 1,001 B

View file

Before

Width:  |  Height:  |  Size: 918 B

After

Width:  |  Height:  |  Size: 918 B

View file

Before

Width:  |  Height:  |  Size: 956 B

After

Width:  |  Height:  |  Size: 956 B

View file

Before

Width:  |  Height:  |  Size: 964 B

After

Width:  |  Height:  |  Size: 964 B

View file

Before

Width:  |  Height:  |  Size: 871 B

After

Width:  |  Height:  |  Size: 871 B

View file

Before

Width:  |  Height:  |  Size: 902 B

After

Width:  |  Height:  |  Size: 902 B

View file

Before

Width:  |  Height:  |  Size: 960 B

After

Width:  |  Height:  |  Size: 960 B

View file

Before

Width:  |  Height:  |  Size: 949 B

After

Width:  |  Height:  |  Size: 949 B

View file

Before

Width:  |  Height:  |  Size: 906 B

After

Width:  |  Height:  |  Size: 906 B

View file

Before

Width:  |  Height:  |  Size: 975 B

After

Width:  |  Height:  |  Size: 975 B

View file

Before

Width:  |  Height:  |  Size: 923 B

After

Width:  |  Height:  |  Size: 923 B

View file

Before

Width:  |  Height:  |  Size: 928 B

After

Width:  |  Height:  |  Size: 928 B

View file

Before

Width:  |  Height:  |  Size: 897 B

After

Width:  |  Height:  |  Size: 897 B

View file

Before

Width:  |  Height:  |  Size: 923 B

After

Width:  |  Height:  |  Size: 923 B

View file

Before

Width:  |  Height:  |  Size: 880 B

After

Width:  |  Height:  |  Size: 880 B

View file

Before

Width:  |  Height:  |  Size: 883 B

After

Width:  |  Height:  |  Size: 883 B

View file

Before

Width:  |  Height:  |  Size: 982 B

After

Width:  |  Height:  |  Size: 982 B

View file

Before

Width:  |  Height:  |  Size: 925 B

After

Width:  |  Height:  |  Size: 925 B

View file

Before

Width:  |  Height:  |  Size: 924 B

After

Width:  |  Height:  |  Size: 924 B

View file

Before

Width:  |  Height:  |  Size: 855 B

After

Width:  |  Height:  |  Size: 855 B

View file

Before

Width:  |  Height:  |  Size: 954 B

After

Width:  |  Height:  |  Size: 954 B

View file

Before

Width:  |  Height:  |  Size: 972 B

After

Width:  |  Height:  |  Size: 972 B

View file

Before

Width:  |  Height:  |  Size: 979 B

After

Width:  |  Height:  |  Size: 979 B

View file

Before

Width:  |  Height:  |  Size: 979 B

After

Width:  |  Height:  |  Size: 979 B

View file

Before

Width:  |  Height:  |  Size: 922 B

After

Width:  |  Height:  |  Size: 922 B

View file

Before

Width:  |  Height:  |  Size: 968 B

After

Width:  |  Height:  |  Size: 968 B

View file

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

View file

Before

Width:  |  Height:  |  Size: 986 B

After

Width:  |  Height:  |  Size: 986 B

View file

Before

Width:  |  Height:  |  Size: 923 B

After

Width:  |  Height:  |  Size: 923 B

View file

Before

Width:  |  Height:  |  Size: 914 B

After

Width:  |  Height:  |  Size: 914 B

View file

Before

Width:  |  Height:  |  Size: 940 B

After

Width:  |  Height:  |  Size: 940 B

View file

Before

Width:  |  Height:  |  Size: 888 B

After

Width:  |  Height:  |  Size: 888 B

View file

Before

Width:  |  Height:  |  Size: 889 B

After

Width:  |  Height:  |  Size: 889 B

View file

Before

Width:  |  Height:  |  Size: 892 B

After

Width:  |  Height:  |  Size: 892 B

View file

Before

Width:  |  Height:  |  Size: 963 B

After

Width:  |  Height:  |  Size: 963 B

View file

Before

Width:  |  Height:  |  Size: 903 B

After

Width:  |  Height:  |  Size: 903 B

View file

Before

Width:  |  Height:  |  Size: 914 B

After

Width:  |  Height:  |  Size: 914 B

View file

Before

Width:  |  Height:  |  Size: 987 B

After

Width:  |  Height:  |  Size: 987 B

View file

Before

Width:  |  Height:  |  Size: 947 B

After

Width:  |  Height:  |  Size: 947 B

View file

Before

Width:  |  Height:  |  Size: 914 B

After

Width:  |  Height:  |  Size: 914 B

View file

Before

Width:  |  Height:  |  Size: 949 B

After

Width:  |  Height:  |  Size: 949 B

View file

Before

Width:  |  Height:  |  Size: 969 B

After

Width:  |  Height:  |  Size: 969 B

View file

Before

Width:  |  Height:  |  Size: 935 B

After

Width:  |  Height:  |  Size: 935 B

View file

Before

Width:  |  Height:  |  Size: 966 B

After

Width:  |  Height:  |  Size: 966 B

View file

Before

Width:  |  Height:  |  Size: 978 B

After

Width:  |  Height:  |  Size: 978 B

View file

Before

Width:  |  Height:  |  Size: 963 B

After

Width:  |  Height:  |  Size: 963 B

View file

Before

Width:  |  Height:  |  Size: 931 B

After

Width:  |  Height:  |  Size: 931 B

View file

Before

Width:  |  Height:  |  Size: 937 B

After

Width:  |  Height:  |  Size: 937 B

View file

Before

Width:  |  Height:  |  Size: 1,002 B

After

Width:  |  Height:  |  Size: 1,002 B

View file

Before

Width:  |  Height:  |  Size: 966 B

After

Width:  |  Height:  |  Size: 966 B

View file

Before

Width:  |  Height:  |  Size: 1,023 B

After

Width:  |  Height:  |  Size: 1,023 B

View file

Before

Width:  |  Height:  |  Size: 910 B

After

Width:  |  Height:  |  Size: 910 B

View file

Before

Width:  |  Height:  |  Size: 947 B

After

Width:  |  Height:  |  Size: 947 B

View file

Before

Width:  |  Height:  |  Size: 998 B

After

Width:  |  Height:  |  Size: 998 B

View file

Before

Width:  |  Height:  |  Size: 961 B

After

Width:  |  Height:  |  Size: 961 B

View file

Before

Width:  |  Height:  |  Size: 975 B

After

Width:  |  Height:  |  Size: 975 B

View file

Before

Width:  |  Height:  |  Size: 892 B

After

Width:  |  Height:  |  Size: 892 B

View file

Before

Width:  |  Height:  |  Size: 967 B

After

Width:  |  Height:  |  Size: 967 B

View file

Before

Width:  |  Height:  |  Size: 959 B

After

Width:  |  Height:  |  Size: 959 B

View file

Before

Width:  |  Height:  |  Size: 899 B

After

Width:  |  Height:  |  Size: 899 B

View file

Before

Width:  |  Height:  |  Size: 720 B

After

Width:  |  Height:  |  Size: 720 B

View file

Before

Width:  |  Height:  |  Size: 851 B

After

Width:  |  Height:  |  Size: 851 B

View file

Before

Width:  |  Height:  |  Size: 992 B

After

Width:  |  Height:  |  Size: 992 B

View file

@ -504,10 +504,12 @@ class ChangeMoodDialog:
self.MOODS.sort()
for mood in self.MOODS:
image = Gtk.Image.new_from_icon_name(
'mood-%s' % mood, Gtk.IconSize.MENU)
self.mood_buttons[mood] = Gtk.RadioButton()
self.mood_buttons[mood].join_group(no_mood_button)
self.mood_buttons[mood].set_mode(False)
self.mood_buttons[mood].add(gtkgui_helpers.load_mood_icon(mood))
self.mood_buttons[mood].add(image)
self.mood_buttons[mood].set_relief(Gtk.ReliefStyle.NONE)
self.mood_buttons[mood].set_tooltip_text(MOODS[mood])
self.mood_buttons[mood].connect('clicked',
@ -700,8 +702,8 @@ class ChangeStatusMessageDialog(TimeoutDialog):
img = self.xml.get_object('mood_image')
label = self.xml.get_object('mood_button_label')
if 'mood' in self.pep_dict and self.pep_dict['mood'] in MOODS:
img.set_from_pixbuf(gtkgui_helpers.load_mood_icon(
self.pep_dict['mood']).get_pixbuf())
img.set_from_icon_name('mood-%s' % self.pep_dict['mood'],
Gtk.IconSize.MENU)
if self.pep_dict['mood_text']:
label.set_text(self.pep_dict['mood_text'])
else:

View file

@ -325,7 +325,7 @@ class ProfileWindow(Gtk.ApplicationWindow):
return
vcard_, sha = self.make_vcard()
nick = vcard_.get('NICKNAME') or None
app.connections[self.account].get_module('UserNickname').send(nick)
app.connections[self.account].get_module('UserNickname').set_nickname(nick)
if not nick:
nick = app.config.get_per('accounts', self.account, 'name')
app.nicks[self.account] = nick

View file

@ -36,11 +36,13 @@ from gi.repository import Pango
from gajim.common import app
from gajim.common import helpers
from gajim.common.const import AvatarSize
from gajim.common.const import PEPEventType
from gajim.common.i18n import Q_
from gajim.common.i18n import _
from gajim.gtk.util import get_builder
from gajim.gtk.util import get_icon_name
from gajim.gtk.util import format_mood
log = logging.getLogger('gajim.gtk.tooltips')
@ -471,8 +473,8 @@ class RosterTooltip(StatusTable):
Append Tune, Mood, Activity, Location information of the specified contact
to the given property list.
"""
if 'mood' in contact.pep:
mood = contact.pep['mood'].as_markup_text()
if PEPEventType.MOOD in contact.pep:
mood = format_mood(*contact.pep[PEPEventType.MOOD])
self._ui.mood.set_markup(mood)
self._ui.mood.show()
self._ui.mood_label.show()

View file

@ -36,6 +36,7 @@ from gajim.common import app
from gajim.common import configpaths
from gajim.common import i18n
from gajim.common.i18n import _
from gajim.common.const import MOODS
from gajim.gtk.const import GajimIconSet
@ -499,3 +500,24 @@ def ensure_not_destroyed(func):
return
return func(self, *args, **kwargs)
return func_wrapper
def ensure_proper_control(func):
@wraps(func)
def func_wrapper(self, event):
if event.account != self.account:
return
if event.jid != self.contact.jid:
return
return func(self, event)
return func_wrapper
def format_mood(mood, text):
if mood is None:
return ''
mood = MOODS[mood]
markuptext = '<b>%s</b>' % GLib.markup_escape_text(mood)
if text is not None:
markuptext += ' (%s)' % GLib.markup_escape_text(text)
return markuptext

View file

@ -267,15 +267,6 @@ def create_list_multi(value_list, selected_values=None):
treeview.show_all()
return treeview
def load_mood_icon(icon_name):
"""
Load an icon from the mood iconset in 16x16
"""
iconset = app.config.get('mood_iconset')
path = os.path.join(helpers.get_mood_iconset_path(iconset), '')
icon_list = _load_icon_list([icon_name], path)
return icon_list[icon_name]
def load_activity_icon(category, activity=None):
"""
Load an icon from the activity iconset in 16x16
@ -289,12 +280,6 @@ def load_activity_icon(category, activity=None):
return icon_list[activity]
def get_pep_icon(pep_class):
if pep_class == PEPEventType.MOOD:
received_mood = pep_class.data['mood']
mood = received_mood if received_mood in MOODS else 'unknown'
pixbuf = load_mood_icon(mood).get_pixbuf()
return pixbuf
if pep_class == PEPEventType.TUNE:
return 'audio-x-generic'

Some files were not shown because too many files have changed in this diff Show more