Daniel Brötzmann pushed to branch mainwindow at gajim / gajim
Commits:
-
a01f9cc5
by wurstsalat at 2021-11-06T21:24:54+01:00
-
4843bf14
by wurstsalat at 2021-11-06T21:25:04+01:00
-
45d775ff
by wurstsalat at 2021-11-06T21:54:57+01:00
-
f4fde9ce
by wurstsalat at 2021-11-06T22:19:30+01:00
4 changed files:
Changes:
| ... | ... | @@ -27,6 +27,10 @@ |
| 27 | 27 |
|
| 28 | 28 |
from typing import Any # pylint: disable=unused-import
|
| 29 | 29 |
from typing import Dict # pylint: disable=unused-import
|
| 30 |
+from typing import Optional
|
|
| 31 |
+from typing import List
|
|
| 32 |
+from typing import Tuple
|
|
| 33 |
+from typing import Union
|
|
| 30 | 34 |
|
| 31 | 35 |
import sys
|
| 32 | 36 |
import re
|
| ... | ... | @@ -62,6 +66,8 @@ |
| 62 | 66 |
from nbxmpp.const import Role
|
| 63 | 67 |
from nbxmpp.const import ConnectionProtocol
|
| 64 | 68 |
from nbxmpp.const import ConnectionType
|
| 69 |
+from nbxmpp.const import Affiliation
|
|
| 70 |
+from nbxmpp.const import Role
|
|
| 65 | 71 |
from nbxmpp.structs import ProxyData
|
| 66 | 72 |
from nbxmpp.protocol import JID
|
| 67 | 73 |
from nbxmpp.protocol import InvalidJid
|
| ... | ... | @@ -163,12 +169,13 @@ def parse_resource(resource): |
| 163 | 169 |
except UnicodeError:
|
| 164 | 170 |
raise InvalidFormat('Invalid character in resource.')
|
| 165 | 171 |
|
| 166 |
-def windowsify(word):
|
|
| 172 |
+def windowsify(word: str) -> str:
|
|
| 167 | 173 |
if os.name == 'nt':
|
| 168 | 174 |
return word.capitalize()
|
| 169 | 175 |
return word
|
| 170 | 176 |
|
| 171 |
-def get_uf_show(show, use_mnemonic=False):
|
|
| 177 |
+def get_uf_show(show: Union[ShowConstant, str],
|
|
| 178 |
+ use_mnemonic: bool = False) -> str:
|
|
| 172 | 179 |
"""
|
| 173 | 180 |
Return a userfriendly string for dnd/xa/chat and make all strings
|
| 174 | 181 |
translatable
|
| ... | ... | @@ -219,7 +226,7 @@ def get_uf_show(show, use_mnemonic=False): |
| 219 | 226 |
uf_show = Q_('?contact has status:Has errors')
|
| 220 | 227 |
return uf_show
|
| 221 | 228 |
|
| 222 |
-def get_uf_sub(sub):
|
|
| 229 |
+def get_uf_sub(sub: str) -> str:
|
|
| 223 | 230 |
if sub == 'none':
|
| 224 | 231 |
uf_sub = Q_('?Subscription we already have:None')
|
| 225 | 232 |
elif sub == 'to':
|
| ... | ... | @@ -233,7 +240,7 @@ def get_uf_sub(sub): |
| 233 | 240 |
|
| 234 | 241 |
return uf_sub
|
| 235 | 242 |
|
| 236 |
-def get_uf_ask(ask):
|
|
| 243 |
+def get_uf_ask(ask: Union[str, None]) -> str:
|
|
| 237 | 244 |
if ask is None:
|
| 238 | 245 |
uf_ask = Q_('?Ask (for Subscription):None')
|
| 239 | 246 |
elif ask == 'subscribe':
|
| ... | ... | @@ -243,7 +250,7 @@ def get_uf_ask(ask): |
| 243 | 250 |
|
| 244 | 251 |
return uf_ask
|
| 245 | 252 |
|
| 246 |
-def get_uf_role(role, plural=False):
|
|
| 253 |
+def get_uf_role(role: Union[Role, str], plural: bool = False) -> str:
|
|
| 247 | 254 |
''' plural determines if you get Moderators or Moderator'''
|
| 248 | 255 |
if not isinstance(role, str):
|
| 249 | 256 |
role = role.value
|
| ... | ... | @@ -267,7 +274,8 @@ def get_uf_role(role, plural=False): |
| 267 | 274 |
role_name = _('Visitor')
|
| 268 | 275 |
return role_name
|
| 269 | 276 |
|
| 270 |
-def get_uf_affiliation(affiliation, plural=False):
|
|
| 277 |
+def get_uf_affiliation(affiliation: Union[Affiliation, str],
|
|
| 278 |
+ plural: bool = False) -> str:
|
|
| 271 | 279 |
'''Get a nice and translated affilition for muc'''
|
| 272 | 280 |
if not isinstance(affiliation, str):
|
| 273 | 281 |
affiliation = affiliation.value
|
| ... | ... | @@ -319,7 +327,7 @@ def get_sorted_keys(adict): |
| 319 | 327 |
keys = sorted(adict.keys())
|
| 320 | 328 |
return keys
|
| 321 | 329 |
|
| 322 |
-def to_one_line(msg):
|
|
| 330 |
+def to_one_line(msg: str) -> str:
|
|
| 323 | 331 |
msg = msg.replace('\\', '\\\\')
|
| 324 | 332 |
msg = msg.replace('\n', '\\n')
|
| 325 | 333 |
# s1 = 'test\ntest\\ntest'
|
| ... | ... | @@ -329,7 +337,7 @@ def to_one_line(msg): |
| 329 | 337 |
# 'test\\ntest\\\\ntest'
|
| 330 | 338 |
return msg
|
| 331 | 339 |
|
| 332 |
-def from_one_line(msg):
|
|
| 340 |
+def from_one_line(msg: str) -> str:
|
|
| 333 | 341 |
# (?<!\\) is a lookbehind assertion which asks anything but '\'
|
| 334 | 342 |
# to match the regexp that follows it
|
| 335 | 343 |
|
| ... | ... | @@ -344,7 +352,7 @@ def from_one_line(msg): |
| 344 | 352 |
# 'test\ntest\\ntest'
|
| 345 | 353 |
return msg
|
| 346 | 354 |
|
| 347 |
-def get_uf_chatstate(chatstate):
|
|
| 355 |
+def get_uf_chatstate(chatstate: str) -> str:
|
|
| 348 | 356 |
"""
|
| 349 | 357 |
Remove chatstate jargon and returns user friendly messages
|
| 350 | 358 |
"""
|
| ... | ... | @@ -393,7 +401,7 @@ def get_file_path_from_dnd_dropped_uri(uri): |
| 393 | 401 |
path = path[5:] # 5 is len('file:')
|
| 394 | 402 |
return path
|
| 395 | 403 |
|
| 396 |
-def sanitize_filename(filename):
|
|
| 404 |
+def sanitize_filename(filename: str) -> str:
|
|
| 397 | 405 |
"""
|
| 398 | 406 |
Make sure the filename we will write does contain only acceptable and latin
|
| 399 | 407 |
characters, and is not too long (in that case hash it)
|
| ... | ... | @@ -413,7 +421,8 @@ def sanitize_filename(filename): |
| 413 | 421 |
|
| 414 | 422 |
return filename
|
| 415 | 423 |
|
| 416 |
-def reduce_chars_newlines(text, max_chars=0, max_lines=0):
|
|
| 424 |
+def reduce_chars_newlines(text: str, max_chars: int = 0,
|
|
| 425 |
+ max_lines: int = 0) -> str:
|
|
| 417 | 426 |
"""
|
| 418 | 427 |
Cut the chars after 'max_chars' on each line and show only the first
|
| 419 | 428 |
'max_lines'
|
| ... | ... | @@ -454,7 +463,8 @@ def get_contact_dict_for_account(account): |
| 454 | 463 |
return contacts_dict
|
| 455 | 464 |
|
| 456 | 465 |
|
| 457 |
-def play_sound(sound_event, account, force=False):
|
|
| 466 |
+def play_sound(sound_event: str, account: str,
|
|
| 467 |
+ force: bool = False) -> None:
|
|
| 458 | 468 |
if sound_event is None:
|
| 459 | 469 |
return
|
| 460 | 470 |
if force or allow_sound_notification(account, sound_event):
|
| ... | ... | @@ -547,7 +557,7 @@ def play_sound_file(path_to_soundfile): |
| 547 | 557 |
except GLib.Error as error:
|
| 548 | 558 |
log.error('Could not play sound: %s', error.message)
|
| 549 | 559 |
|
| 550 |
-def get_connection_status(account):
|
|
| 560 |
+def get_connection_status(account: str) -> str:
|
|
| 551 | 561 |
con = app.connections[account]
|
| 552 | 562 |
if con.state.is_reconnect_scheduled:
|
| 553 | 563 |
return 'error'
|
| ... | ... | @@ -559,7 +569,7 @@ def get_connection_status(account): |
| 559 | 569 |
return 'offline'
|
| 560 | 570 |
return con.status
|
| 561 | 571 |
|
| 562 |
-def get_global_show():
|
|
| 572 |
+def get_global_show() -> str:
|
|
| 563 | 573 |
maxi = 0
|
| 564 | 574 |
for account in app.connections:
|
| 565 | 575 |
if not app.settings.get_account_setting(account,
|
| ... | ... | @@ -571,7 +581,7 @@ def get_global_show(): |
| 571 | 581 |
maxi = index
|
| 572 | 582 |
return SHOW_LIST[maxi]
|
| 573 | 583 |
|
| 574 |
-def get_global_status_message():
|
|
| 584 |
+def get_global_status_message() -> str:
|
|
| 575 | 585 |
maxi = 0
|
| 576 | 586 |
for account in app.connections:
|
| 577 | 587 |
if not app.settings.get_account_setting(account,
|
| ... | ... | @@ -584,7 +594,7 @@ def get_global_status_message(): |
| 584 | 594 |
status_message = app.connections[account].status_message
|
| 585 | 595 |
return status_message
|
| 586 | 596 |
|
| 587 |
-def statuses_unified():
|
|
| 597 |
+def statuses_unified() -> bool:
|
|
| 588 | 598 |
"""
|
| 589 | 599 |
Test if all statuses are the same
|
| 590 | 600 |
"""
|
| ... | ... | @@ -628,7 +638,7 @@ def remove_invalid_xml_chars(string_): |
| 628 | 638 |
string_ = re.sub(INVALID_XML_CHARS_REGEX, '', string_)
|
| 629 | 639 |
return string_
|
| 630 | 640 |
|
| 631 |
-def get_random_string(count=16):
|
|
| 641 |
+def get_random_string(count: int = 16) -> str:
|
|
| 632 | 642 |
"""
|
| 633 | 643 |
Create random string of count length
|
| 634 | 644 |
|
| ... | ... | @@ -638,7 +648,7 @@ def get_random_string(count=16): |
| 638 | 648 |
return ''.join(random.choice(allowed) for char in range(count))
|
| 639 | 649 |
|
| 640 | 650 |
@functools.lru_cache(maxsize=1)
|
| 641 |
-def get_os_info():
|
|
| 651 |
+def get_os_info() -> str:
|
|
| 642 | 652 |
info = 'N/A'
|
| 643 | 653 |
if sys.platform in ('win32', 'darwin'):
|
| 644 | 654 |
info = f'{platform.system()} {platform.release()}'
|
| ... | ... | @@ -680,7 +690,7 @@ def message_needs_highlight(text, nickname, own_jid): |
| 680 | 690 |
return False
|
| 681 | 691 |
|
| 682 | 692 |
|
| 683 |
-def allow_showing_notification(account):
|
|
| 693 |
+def allow_showing_notification(account: str) -> bool:
|
|
| 684 | 694 |
if not app.settings.get('show_notifications'):
|
| 685 | 695 |
return False
|
| 686 | 696 |
if app.settings.get('show_notifications_away'):
|
| ... | ... | @@ -690,7 +700,7 @@ def allow_showing_notification(account): |
| 690 | 700 |
return False
|
| 691 | 701 |
|
| 692 | 702 |
|
| 693 |
-def allow_sound_notification(account, sound_event):
|
|
| 703 |
+def allow_sound_notification(account: str, sound_event: str) -> bool:
|
|
| 694 | 704 |
if not app.settings.get('sounds_on'):
|
| 695 | 705 |
return False
|
| 696 | 706 |
client = app.get_client(account)
|
| ... | ... | @@ -730,23 +740,25 @@ def jid_is_blocked(account, jid): |
| 730 | 740 |
con = app.connections[account]
|
| 731 | 741 |
return jid in con.get_module('Blocking').blocked
|
| 732 | 742 |
|
| 733 |
-def get_subscription_request_msg(account=None):
|
|
| 734 |
- s = app.settings.get_account_setting(account, 'subscription_request_msg')
|
|
| 735 |
- if s:
|
|
| 736 |
- return s
|
|
| 737 |
- s = _('I would like to add you to my contact list.')
|
|
| 738 |
- if account:
|
|
| 739 |
- s = _('Hello, I am $name.') + ' ' + s
|
|
| 740 |
- s = Template(s).safe_substitute({'name': app.nicks[account]})
|
|
| 741 |
- return s
|
|
| 742 |
- |
|
| 743 |
-def get_user_proxy(account):
|
|
| 743 |
+def get_subscription_request_msg(account: Optional[str] = None) -> str:
|
|
| 744 |
+ message = _('I would like to add you to my contact list.')
|
|
| 745 |
+ if account is None:
|
|
| 746 |
+ return message
|
|
| 747 |
+
|
|
| 748 |
+ message = app.settings.get_account_setting(account, 'subscription_request_msg')
|
|
| 749 |
+ if message:
|
|
| 750 |
+ return message
|
|
| 751 |
+ |
|
| 752 |
+ message = _('Hello, I am $name. %s') % message
|
|
| 753 |
+ return Template(message).safe_substitute({'name': app.nicks[account]})
|
|
| 754 |
+ |
|
| 755 |
+def get_user_proxy(account: str) -> Optional[ProxyData]:
|
|
| 744 | 756 |
proxy_name = app.settings.get_account_setting(account, 'proxy')
|
| 745 | 757 |
if not proxy_name:
|
| 746 | 758 |
return None
|
| 747 | 759 |
return get_proxy(proxy_name)
|
| 748 | 760 |
|
| 749 |
-def get_proxy(proxy_name):
|
|
| 761 |
+def get_proxy(proxy_name: str) -> Optional[ProxyData]:
|
|
| 750 | 762 |
try:
|
| 751 | 763 |
settings = app.settings.get_proxy_settings(proxy_name)
|
| 752 | 764 |
except ValueError:
|
| ... | ... | @@ -926,7 +938,7 @@ def func_wrapper(self, *args, **kwargs): |
| 926 | 938 |
return func_wrapper
|
| 927 | 939 |
|
| 928 | 940 |
|
| 929 |
-def parse_uri_actions(uri):
|
|
| 941 |
+def parse_uri_actions(uri: str) -> Tuple[str, Dict[str, str]]:
|
|
| 930 | 942 |
uri = uri[5:]
|
| 931 | 943 |
if '?' not in uri:
|
| 932 | 944 |
return 'message', {'jid': uri}
|
| ... | ... | @@ -948,7 +960,7 @@ def parse_uri_actions(uri): |
| 948 | 960 |
return action, data
|
| 949 | 961 |
|
| 950 | 962 |
|
| 951 |
-def parse_uri(uri):
|
|
| 963 |
+def parse_uri(uri: str) -> URI:
|
|
| 952 | 964 |
if uri.startswith('xmpp:'):
|
| 953 | 965 |
action, data = parse_uri_actions(uri)
|
| 954 | 966 |
try:
|
| ... | ... | @@ -990,7 +1002,7 @@ def parse_uri(uri): |
| 990 | 1002 |
|
| 991 | 1003 |
|
| 992 | 1004 |
@catch_exceptions
|
| 993 |
-def open_uri(uri, account=None):
|
|
| 1005 |
+def open_uri(uri: Union[URI, str], account: Optional[str] = None) -> None:
|
|
| 994 | 1006 |
if not isinstance(uri, URI):
|
| 995 | 1007 |
uri = parse_uri(uri)
|
| 996 | 1008 |
|
| ... | ... | @@ -1023,13 +1035,17 @@ def open_uri(uri, account=None): |
| 1023 | 1035 |
log.warning('Account must be specified to open XMPP uri')
|
| 1024 | 1036 |
return
|
| 1025 | 1037 |
|
| 1038 |
+ if isinstance(uri.data, dict):
|
|
| 1039 |
+ jid = uri.data['jid']
|
|
| 1040 |
+ message = uri.data.get('body')
|
|
| 1041 |
+ else:
|
|
| 1042 |
+ log.warning('Cant open URI: %s', uri)
|
|
| 1026 | 1043 |
if uri.action == URIAction.JOIN:
|
| 1027 | 1044 |
app.app.activate_action(
|
| 1028 | 1045 |
'groupchat-join',
|
| 1029 |
- GLib.Variant('as', [account, uri.data['jid']]))
|
|
| 1046 |
+ GLib.Variant('as', [account, jid]))
|
|
| 1030 | 1047 |
elif uri.action == URIAction.MESSAGE:
|
| 1031 |
- app.interface.start_chat_from_jid(account, uri.data['jid'],
|
|
| 1032 |
- message=uri.data.get('body'))
|
|
| 1048 |
+ app.interface.start_chat_from_jid(account, jid, message=message)
|
|
| 1033 | 1049 |
else:
|
| 1034 | 1050 |
log.warning('Cant open URI: %s', uri)
|
| 1035 | 1051 |
|
| ... | ... | @@ -1080,9 +1096,8 @@ def file_is_locked(path_to_file): |
| 1080 | 1096 |
return False
|
| 1081 | 1097 |
|
| 1082 | 1098 |
|
| 1083 |
-def geo_provider_from_location(lat, lon):
|
|
| 1084 |
- return ('https://www.openstreetmap.org/?'
|
|
| 1085 |
- 'mlat=%s&mlon=%s&zoom=16') % (lat, lon)
|
|
| 1099 |
+def geo_provider_from_location(lat: str, lon: str) -> str:
|
|
| 1100 |
+ return f'https://www.openstreetmap.org/?mlat={lat}&mlon={lon}&zoom=16'
|
|
| 1086 | 1101 |
|
| 1087 | 1102 |
|
| 1088 | 1103 |
def get_resource(account):
|
| ... | ... | @@ -1097,7 +1112,7 @@ def get_resource(account): |
| 1097 | 1112 |
return resource
|
| 1098 | 1113 |
|
| 1099 | 1114 |
|
| 1100 |
-def get_default_muc_config():
|
|
| 1115 |
+def get_default_muc_config() -> Dict[str, Union[bool, str]]:
|
|
| 1101 | 1116 |
return {
|
| 1102 | 1117 |
# XEP-0045 options
|
| 1103 | 1118 |
'muc#roomconfig_allowinvites': True,
|
| ... | ... | @@ -1182,10 +1197,10 @@ def is_role_change_allowed(self_contact, contact): |
| 1182 | 1197 |
return self_contact.affiliation >= contact.affiliation
|
| 1183 | 1198 |
|
| 1184 | 1199 |
|
| 1185 |
-def get_tls_error_phrase(tls_error):
|
|
| 1200 |
+def get_tls_error_phrase(tls_error: Gio.TlsCertificateFlags) -> str:
|
|
| 1186 | 1201 |
phrase = GIO_TLS_ERRORS.get(tls_error)
|
| 1187 | 1202 |
if phrase is None:
|
| 1188 |
- return GIO_TLS_ERRORS.get(Gio.TlsCertificateFlags.GENERIC_ERROR)
|
|
| 1203 |
+ return GIO_TLS_ERRORS[Gio.TlsCertificateFlags.GENERIC_ERROR]
|
|
| 1189 | 1204 |
return phrase
|
| 1190 | 1205 |
|
| 1191 | 1206 |
|
| ... | ... | @@ -1296,7 +1311,8 @@ def convert_gio_to_openssl_cert(cert): |
| 1296 | 1311 |
return cert
|
| 1297 | 1312 |
|
| 1298 | 1313 |
|
| 1299 |
-def get_custom_host(account):
|
|
| 1314 |
+def get_custom_host(account: str
|
|
| 1315 |
+ ) -> Optional[Tuple[str, ConnectionProtocol, str]]:
|
|
| 1300 | 1316 |
if not app.settings.get_account_setting(account, 'use_custom_host'):
|
| 1301 | 1317 |
return None
|
| 1302 | 1318 |
host = app.settings.get_account_setting(account, 'custom_host')
|
| ... | ... | @@ -1312,7 +1328,9 @@ def get_custom_host(account): |
| 1312 | 1328 |
return (host, protocol, ConnectionType(type_))
|
| 1313 | 1329 |
|
| 1314 | 1330 |
|
| 1315 |
-def warn_about_plain_connection(account, connection_types):
|
|
| 1331 |
+def warn_about_plain_connection(account: str,
|
|
| 1332 |
+ connection_types: List[ConnectionType]
|
|
| 1333 |
+ ) -> bool:
|
|
| 1316 | 1334 |
warn = app.settings.get_account_setting(
|
| 1317 | 1335 |
account, 'confirm_unencrypted_connection')
|
| 1318 | 1336 |
for type_ in connection_types:
|
| ... | ... | @@ -1321,7 +1339,7 @@ def warn_about_plain_connection(account, connection_types): |
| 1321 | 1339 |
return False
|
| 1322 | 1340 |
|
| 1323 | 1341 |
|
| 1324 |
-def get_idle_status_message(state, status_message):
|
|
| 1342 |
+def get_idle_status_message(state: str, status_message: str) -> str:
|
|
| 1325 | 1343 |
message = app.settings.get(f'auto{state}_message')
|
| 1326 | 1344 |
if not message:
|
| 1327 | 1345 |
message = status_message
|
| ... | ... | @@ -1349,7 +1367,7 @@ def should_log(account, jid): |
| 1349 | 1367 |
return (account not in no_log_for) and (jid not in no_log_for)
|
| 1350 | 1368 |
|
| 1351 | 1369 |
|
| 1352 |
-def ask_for_status_message(status, signin=False):
|
|
| 1370 |
+def ask_for_status_message(status: str, signin: bool = False) -> bool:
|
|
| 1353 | 1371 |
if status is None:
|
| 1354 | 1372 |
# We try to change the message
|
| 1355 | 1373 |
return True
|
| ... | ... | @@ -12,8 +12,14 @@ |
| 12 | 12 |
# You should have received a copy of the GNU General Public License
|
| 13 | 13 |
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
| 14 | 14 |
|
| 15 |
+from typing import Dict
|
|
| 16 |
+from typing import NamedTuple
|
|
| 17 |
+from typing import Optional
|
|
| 18 |
+from typing import Tuple
|
|
| 19 |
+from typing import Union
|
|
| 20 |
+from typing import Any
|
|
| 21 |
+ |
|
| 15 | 22 |
import time
|
| 16 |
-from collections import namedtuple
|
|
| 17 | 23 |
from dataclasses import dataclass
|
| 18 | 24 |
|
| 19 | 25 |
from nbxmpp.protocol import JID
|
| ... | ... | @@ -23,9 +29,14 @@ |
| 23 | 29 |
from gajim.common.const import MUCJoinedState
|
| 24 | 30 |
from gajim.common.const import KindConstant
|
| 25 | 31 |
from gajim.common.const import PresenceShowExt
|
| 32 |
+from gajim.common.const import URIType
|
|
| 33 |
+from gajim.common.const import URIAction
|
|
| 34 |
+ |
|
| 26 | 35 |
|
| 27 |
-URI = namedtuple('URI', 'type action data')
|
|
| 28 |
-URI.__new__.__defaults__ = (None, None) # type: ignore
|
|
| 36 |
+class URI(NamedTuple):
|
|
| 37 |
+ type: URIType
|
|
| 38 |
+ action: Optional[URIAction] = None
|
|
| 39 |
+ data: Optional[Union[Dict[str, str], str]] = None
|
|
| 29 | 40 |
|
| 30 | 41 |
|
| 31 | 42 |
class MUCData:
|
| ... | ... | @@ -44,6 +44,7 @@ |
| 44 | 44 |
from gi.repository import Pango
|
| 45 | 45 |
from gi.repository import GdkPixbuf
|
| 46 | 46 |
import nbxmpp
|
| 47 |
+from nbxmpp.structs import LocationData
|
|
| 47 | 48 |
import cairo
|
| 48 | 49 |
|
| 49 | 50 |
from gajim.common import app
|
| ... | ... | @@ -263,7 +264,7 @@ def get_icon_name(name: str, |
| 263 | 264 |
return '%s-%s' % (iconset, name)
|
| 264 | 265 |
|
| 265 | 266 |
|
| 266 |
-def load_user_iconsets():
|
|
| 267 |
+def load_user_iconsets() -> None:
|
|
| 267 | 268 |
iconsets_path = configpaths.get('MY_ICONSETS')
|
| 268 | 269 |
if not iconsets_path.exists():
|
| 269 | 270 |
return
|
| ... | ... | @@ -275,7 +276,7 @@ def load_user_iconsets(): |
| 275 | 276 |
_icon_theme.append_search_path(str(path))
|
| 276 | 277 |
|
| 277 | 278 |
|
| 278 |
-def get_available_iconsets():
|
|
| 279 |
+def get_available_iconsets() -> List[str]:
|
|
| 279 | 280 |
iconsets = []
|
| 280 | 281 |
for iconset in GajimIconSet:
|
| 281 | 282 |
iconsets.append(iconset.value)
|
| ... | ... | @@ -421,7 +422,7 @@ def at_the_end(widget: Gtk.ScrolledWindow) -> bool: |
| 421 | 422 |
|
| 422 | 423 |
|
| 423 | 424 |
def get_image_button(icon_name: str, tooltip: str,
|
| 424 |
- toggle: Optional[bool] = False) -> Gtk.Button:
|
|
| 425 |
+ toggle: bool = False) -> Gtk.Button:
|
|
| 425 | 426 |
if toggle:
|
| 426 | 427 |
button = Gtk.ToggleButton()
|
| 427 | 428 |
image = Gtk.Image.new_from_icon_name(icon_name, Gtk.IconSize.MENU)
|
| ... | ... | @@ -534,7 +535,7 @@ def func_wrapper(self, *args, **kwargs): |
| 534 | 535 |
return func_wrapper
|
| 535 | 536 |
|
| 536 | 537 |
|
| 537 |
-def format_mood(mood, text):
|
|
| 538 |
+def format_mood(mood: str, text: str) -> str:
|
|
| 538 | 539 |
if mood is None:
|
| 539 | 540 |
return ''
|
| 540 | 541 |
mood = MOODS[mood]
|
| ... | ... | @@ -544,13 +545,13 @@ def format_mood(mood, text): |
| 544 | 545 |
return markuptext
|
| 545 | 546 |
|
| 546 | 547 |
|
| 547 |
-def get_account_mood_icon_name(account):
|
|
| 548 |
+def get_account_mood_icon_name(account: str) -> Optional[str]:
|
|
| 548 | 549 |
client = app.get_client(account)
|
| 549 | 550 |
mood = client.get_module('UserMood').get_current_mood()
|
| 550 | 551 |
return f'mood-{mood.mood}' if mood is not None else mood
|
| 551 | 552 |
|
| 552 | 553 |
|
| 553 |
-def format_activity(activity, subactivity, text):
|
|
| 554 |
+def format_activity(activity: str, subactivity: str, text: str) -> str:
|
|
| 554 | 555 |
if subactivity in ACTIVITIES[activity]:
|
| 555 | 556 |
subactivity = ACTIVITIES[activity][subactivity]
|
| 556 | 557 |
activity = ACTIVITIES[activity]['category']
|
| ... | ... | @@ -564,14 +565,15 @@ def format_activity(activity, subactivity, text): |
| 564 | 565 |
return markuptext
|
| 565 | 566 |
|
| 566 | 567 |
|
| 567 |
-def get_activity_icon_name(activity, subactivity=None):
|
|
| 568 |
+def get_activity_icon_name(activity: str,
|
|
| 569 |
+ subactivity: Optional[str] = None) -> str:
|
|
| 568 | 570 |
icon_name = 'activity-%s' % activity.replace('_', '-')
|
| 569 | 571 |
if subactivity is not None:
|
| 570 | 572 |
icon_name += '-%s' % subactivity.replace('_', '-')
|
| 571 | 573 |
return icon_name
|
| 572 | 574 |
|
| 573 | 575 |
|
| 574 |
-def get_account_activity_icon_name(account):
|
|
| 576 |
+def get_account_activity_icon_name(account: str) -> Optional[str]:
|
|
| 575 | 577 |
client = app.get_client(account)
|
| 576 | 578 |
activity = client.get_module('UserActivity').get_current_activity()
|
| 577 | 579 |
if activity is None:
|
| ... | ... | @@ -579,7 +581,8 @@ def get_account_activity_icon_name(account): |
| 579 | 581 |
return get_activity_icon_name(activity.activity, activity.subactivity)
|
| 580 | 582 |
|
| 581 | 583 |
|
| 582 |
-def format_tune(artist, _length, _rating, source, title, _track, _uri):
|
|
| 584 |
+def format_tune(artist: str, _length: str, _rating: str, source: str,
|
|
| 585 |
+ title: str, _track: str, _uri: str) -> str:
|
|
| 583 | 586 |
artist = GLib.markup_escape_text(artist or _('Unknown Artist'))
|
| 584 | 587 |
title = GLib.markup_escape_text(title or _('Unknown Title'))
|
| 585 | 588 |
source = GLib.markup_escape_text(source or _('Unknown Source'))
|
| ... | ... | @@ -591,13 +594,13 @@ def format_tune(artist, _length, _rating, source, title, _track, _uri): |
| 591 | 594 |
return tune_string
|
| 592 | 595 |
|
| 593 | 596 |
|
| 594 |
-def get_account_tune_icon_name(account):
|
|
| 597 |
+def get_account_tune_icon_name(account: str) -> Optional[str]:
|
|
| 595 | 598 |
client = app.get_client(account)
|
| 596 | 599 |
tune = client.get_module('UserTune').get_current_tune()
|
| 597 | 600 |
return None if tune is None else 'audio-x-generic'
|
| 598 | 601 |
|
| 599 | 602 |
|
| 600 |
-def format_location(location):
|
|
| 603 |
+def format_location(location: LocationData) -> str:
|
|
| 601 | 604 |
location = location._asdict()
|
| 602 | 605 |
location_string = ''
|
| 603 | 606 |
for attr, value in location.items():
|
| ... | ... | @@ -614,7 +617,7 @@ def format_location(location): |
| 614 | 617 |
return location_string.strip()
|
| 615 | 618 |
|
| 616 | 619 |
|
| 617 |
-def get_account_location_icon_name(account):
|
|
| 620 |
+def get_account_location_icon_name(account: str) -> Optional[str]:
|
|
| 618 | 621 |
client = app.get_client(account)
|
| 619 | 622 |
location = client.get_module('UserLocation').get_current_location()
|
| 620 | 623 |
return None if location is None else 'applications-internet'
|
| ... | ... | @@ -625,7 +628,7 @@ def format_eta(time_: Union[int, float]) -> str: |
| 625 | 628 |
time_ = int(time_)
|
| 626 | 629 |
times['seconds'] = time_ % 60
|
| 627 | 630 |
if time_ >= 60:
|
| 628 |
- time_ /= 60
|
|
| 631 |
+ time_ = int(time_ / 60)
|
|
| 629 | 632 |
times['minutes'] = round(time_ % 60)
|
| 630 | 633 |
return _('%(minutes)s min %(seconds)s s') % times
|
| 631 | 634 |
return _('%s s') % times['seconds']
|
| ... | ... | @@ -705,7 +708,7 @@ def get_css_show_class(show: str) -> str: |
| 705 | 708 |
return '.gajim-status-offline'
|
| 706 | 709 |
|
| 707 | 710 |
|
| 708 |
-def add_css_to_widget(widget, css):
|
|
| 711 |
+def add_css_to_widget(widget: Any, css: str) -> None:
|
|
| 709 | 712 |
provider = Gtk.CssProvider()
|
| 710 | 713 |
provider.load_from_data(bytes(css.encode()))
|
| 711 | 714 |
context = widget.get_style_context()
|
| ... | ... | @@ -713,7 +716,7 @@ def add_css_to_widget(widget, css): |
| 713 | 716 |
Gtk.STYLE_PROVIDER_PRIORITY_USER)
|
| 714 | 717 |
|
| 715 | 718 |
|
| 716 |
-def get_pixbuf_from_data(file_data):
|
|
| 719 |
+def get_pixbuf_from_data(file_data: bytes) -> Optional[GdkPixbuf.Pixbuf]:
|
|
| 717 | 720 |
# TODO: This already exists in preview_helpery pixbuf_from_data
|
| 718 | 721 |
"""
|
| 719 | 722 |
Get image data and returns GdkPixbuf.Pixbuf
|
| ... | ... | @@ -738,7 +741,7 @@ def get_pixbuf_from_data(file_data): |
| 738 | 741 |
except Exception:
|
| 739 | 742 |
log.warning('Could not use pillow to convert avatar image, '
|
| 740 | 743 |
'image cannot be displayed', exc_info=True)
|
| 741 |
- return
|
|
| 744 |
+ return None
|
|
| 742 | 745 |
|
| 743 | 746 |
return pixbuf
|
| 744 | 747 |
|
| ... | ... | @@ -763,7 +766,7 @@ def scale_pixbuf(pixbuf: GdkPixbuf.Pixbuf, |
| 763 | 766 |
GdkPixbuf.InterpType.BILINEAR)
|
| 764 | 767 |
|
| 765 | 768 |
|
| 766 |
-def scale_pixbuf_from_data(data, size):
|
|
| 769 |
+def scale_pixbuf_from_data(data: bytes, size: int) -> Optional[GdkPixbuf.Pixbuf]:
|
|
| 767 | 770 |
pixbuf = get_pixbuf_from_data(data)
|
| 768 | 771 |
return scale_pixbuf(pixbuf, size)
|
| 769 | 772 |
|
| ... | ... | @@ -821,7 +824,7 @@ def get_thumbnail_size(pixbuf: GdkPixbuf.Pixbuf, size: int) -> Tuple[int, int]: |
| 821 | 824 |
return image_width, image_height
|
| 822 | 825 |
|
| 823 | 826 |
|
| 824 |
-def make_href_markup(string):
|
|
| 827 |
+def make_href_markup(string: str) -> str:
|
|
| 825 | 828 |
url_color = app.css_config.get_value('.gajim-url', StyleAttr.COLOR)
|
| 826 | 829 |
color = convert_rgb_to_hex(url_color)
|
| 827 | 830 |
|
| ... | ... | @@ -14,13 +14,19 @@ |
| 14 | 14 |
# You should have received a copy of the GNU General Public License
|
| 15 | 15 |
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
| 16 | 16 |
|
| 17 |
-from typing import Optional
|
|
| 17 |
+from typing import Tuple
|
|
| 18 |
+from typing import List
|
|
| 19 |
+from typing import Union
|
|
| 20 |
+from typing import Any
|
|
| 21 |
+ |
|
| 18 | 22 |
from urllib.parse import quote
|
| 19 | 23 |
|
| 20 | 24 |
from gi.repository import Gtk
|
| 21 | 25 |
from gi.repository import Gio
|
| 22 | 26 |
from gi.repository import GLib
|
| 23 | 27 |
|
| 28 |
+from nbxmpp import JID
|
|
| 29 |
+ |
|
| 24 | 30 |
from gajim.common import app
|
| 25 | 31 |
from gajim.common.helpers import is_affiliation_change_allowed
|
| 26 | 32 |
from gajim.common.helpers import is_role_change_allowed
|
| ... | ... | @@ -35,11 +41,12 @@ |
| 35 | 41 |
from gajim.gui.const import ControlType
|
| 36 | 42 |
|
| 37 | 43 |
|
| 38 |
-def get_singlechat_menu(control_id, account, jid, type_):
|
|
| 44 |
+def get_singlechat_menu(control_id: str, account: str, jid: JID,
|
|
| 45 |
+ type_: ControlType) -> Gio.Menu:
|
|
| 39 | 46 |
client = app.get_client(account)
|
| 40 | 47 |
is_self_contact = jid.bare == client.get_own_jid().bare
|
| 41 | 48 |
|
| 42 |
- singlechat_menu = [
|
|
| 49 |
+ singlechat_menu: List[Any] = [
|
|
| 43 | 50 |
(_('Send File'), [
|
| 44 | 51 |
('win.send-file-httpupload-', _('Upload File…')),
|
| 45 | 52 |
('win.send-file-jingle-', _('Send File Directly…'))
|
| ... | ... | @@ -117,7 +124,7 @@ def build_menu(preset): |
| 117 | 124 |
return build_menu(singlechat_menu)
|
| 118 | 125 |
|
| 119 | 126 |
|
| 120 |
-def get_groupchat_menu(control_id, account, jid):
|
|
| 127 |
+def get_groupchat_menu(control_id: str, account: str, jid: str) -> Gio.Menu:
|
|
| 121 | 128 |
groupchat_menu = [
|
| 122 | 129 |
('win.information-', _('Information')),
|
| 123 | 130 |
('win.groupchat-settings-', _('Settings…')),
|
| ... | ... | @@ -219,7 +226,7 @@ def build_menu(preset): |
| 219 | 226 |
return build_menu(account_menu)
|
| 220 | 227 |
|
| 221 | 228 |
|
| 222 |
-def build_accounts_menu():
|
|
| 229 |
+def build_accounts_menu() -> None:
|
|
| 223 | 230 |
menubar = app.app.get_menubar()
|
| 224 | 231 |
# Accounts Submenu
|
| 225 | 232 |
menu_position = 1
|
| ... | ... | @@ -259,7 +266,7 @@ def build_accounts_menu(): |
| 259 | 266 |
|
| 260 | 267 |
|
| 261 | 268 |
def get_encryption_menu(control_id: str, control_type: ControlType,
|
| 262 |
- zeroconf: Optional[bool] = False) -> Gio.Menu:
|
|
| 269 |
+ zeroconf: bool = False) -> Gio.Menu:
|
|
| 263 | 270 |
menu = Gio.Menu()
|
| 264 | 271 |
menu.append(
|
| 265 | 272 |
_('Disabled'), f'win.set-encryption-{control_id}::disabled')
|
| ... | ... | @@ -405,7 +412,10 @@ def get_conv_uri_context_menu(account: str, uri: URI) -> Gtk.Menu: |
| 405 | 412 |
|
| 406 | 413 |
data = uri.data
|
| 407 | 414 |
if uri.type == URIType.XMPP:
|
| 408 |
- data = uri.data['jid']
|
|
| 415 |
+ if isinstance(uri.data, dict):
|
|
| 416 |
+ data = uri.data['jid']
|
|
| 417 |
+ else:
|
|
| 418 |
+ data = ''
|
|
| 409 | 419 |
|
| 410 | 420 |
if action in ('app.open-mail', 'app.copy-text'):
|
| 411 | 421 |
value = GLib.Variant.new_string(data)
|
| ... | ... | @@ -417,7 +427,7 @@ def get_conv_uri_context_menu(account: str, uri: URI) -> Gtk.Menu: |
| 417 | 427 |
return menu
|
| 418 | 428 |
|
| 419 | 429 |
|
| 420 |
-def get_roster_menu(account, jid, gateway=False):
|
|
| 430 |
+def get_roster_menu(account: str, jid: str, gateway: bool = False) -> Gio.Menu:
|
|
| 421 | 431 |
if jid_is_blocked(account, jid):
|
| 422 | 432 |
block_label = _('Unblock')
|
| 423 | 433 |
else:
|
| ... | ... | @@ -436,14 +446,14 @@ def get_roster_menu(account, jid, gateway=False): |
| 436 | 446 |
action, label = item
|
| 437 | 447 |
action = f'win.{action}-{account}'
|
| 438 | 448 |
menuitem = Gio.MenuItem.new(label, action)
|
| 439 |
- variant = GLib.Variant('s', str(jid))
|
|
| 449 |
+ variant = GLib.Variant('s', jid)
|
|
| 440 | 450 |
menuitem.set_action_and_target_value(action, variant)
|
| 441 | 451 |
menu.append_item(menuitem)
|
| 442 | 452 |
|
| 443 | 453 |
return menu
|
| 444 | 454 |
|
| 445 | 455 |
|
| 446 |
-def get_subscription_menu(account, jid):
|
|
| 456 |
+def get_subscription_menu(account: str, jid: str) -> Gio.Menu:
|
|
| 447 | 457 |
menu = Gio.Menu()
|
| 448 | 458 |
|
| 449 | 459 |
action_name = 'win.add-chat'
|
| ... | ... | @@ -475,13 +485,15 @@ def get_subscription_menu(account, jid): |
| 475 | 485 |
return menu
|
| 476 | 486 |
|
| 477 | 487 |
|
| 478 |
-def get_chat_list_row_menu(workspace_id, account, jid, pinned):
|
|
| 488 |
+def get_chat_list_row_menu(workspace_id: str, account: str,
|
|
| 489 |
+ jid: Union[JID, str], pinned: bool) -> Gio.Menu:
|
|
| 490 |
+ jid = str(jid)
|
|
| 479 | 491 |
client = app.get_client(account)
|
| 480 | 492 |
contact = client.get_module('Contacts').get_contact(jid)
|
| 481 | 493 |
|
| 482 | 494 |
toggle_label = _('Unpin Chat') if pinned else _('Pin Chat')
|
| 483 | 495 |
|
| 484 |
- menu_items = [
|
|
| 496 |
+ menu_items: List[Any] = [
|
|
| 485 | 497 |
('toggle-chat-pinned', toggle_label),
|
| 486 | 498 |
]
|
| 487 | 499 |
|
| ... | ... | @@ -502,20 +514,21 @@ def get_chat_list_row_menu(workspace_id, account, jid, pinned): |
| 502 | 514 |
action = f'win.{action}'
|
| 503 | 515 |
menuitem = Gio.MenuItem.new(label, action)
|
| 504 | 516 |
variant_list = GLib.Variant(
|
| 505 |
- 'as', [workspace_id, account, str(jid)])
|
|
| 517 |
+ 'as', [workspace_id, account, jid])
|
|
| 506 | 518 |
menuitem.set_action_and_target_value(action, variant_list)
|
| 507 | 519 |
menu.append_item(menuitem)
|
| 508 | 520 |
else:
|
| 509 | 521 |
# This is a submenu
|
| 510 | 522 |
if len(workspaces) > 1:
|
| 511 | 523 |
submenu = build_workspaces_submenu(
|
| 512 |
- workspace_id, account, str(jid))
|
|
| 524 |
+ workspace_id, account, jid)
|
|
| 513 | 525 |
menu.append_submenu(item[0], submenu)
|
| 514 | 526 |
|
| 515 | 527 |
return menu
|
| 516 | 528 |
|
| 517 | 529 |
|
| 518 |
-def build_workspaces_submenu(current_workspace_id, account, jid):
|
|
| 530 |
+def build_workspaces_submenu(current_workspace_id: str, account: str,
|
|
| 531 |
+ jid: str) -> Gio.Menu:
|
|
| 519 | 532 |
submenu = Gio.Menu()
|
| 520 | 533 |
for workspace_id in app.settings.get_workspaces():
|
| 521 | 534 |
if workspace_id == current_workspace_id:
|