Philipp Hörist pushed to branch master at gajim / gajim
Commits:
-
5a906c14
by Philipp Hörist at 2018-09-21T13:46:52Z
-
3f2f51c1
by Philipp Hörist at 2018-09-21T13:46:52Z
-
4d4d0023
by Philipp Hörist at 2018-09-21T13:46:52Z
-
f7a2ac9d
by Philipp Hörist at 2018-09-21T13:46:52Z
-
74b66837
by Philipp Hörist at 2018-09-21T13:46:52Z
16 changed files:
- gajim/accounts_window.py
- gajim/common/app.py
- gajim/common/types.py
- gajim/config.py
- gajim/gtk/account_wizard.py
- + gajim/gtk/const.py
- gajim/gtk/emoji_data.py
- gajim/gtk/emoji_data.pyi
- gajim/gtk/filechoosers.py
- + gajim/gtk/types.py
- gajim/gtkexcepthook.py
- gajim/gui_interface.py
- gajim/htmltextview.py
- gajim/plugins/gajimplugin.py
- + test/gtk/htmltextview.py
- test/lib/gajim_mocks.py
Changes:
| ... | ... | @@ -258,10 +258,8 @@ class AccountsWindow(Gtk.ApplicationWindow): |
| 258 | 258 |
'accounts', account, 'name')
|
| 259 | 259 |
app.block_signed_in_notifications[account] = True
|
| 260 | 260 |
app.sleeper_state[account] = 'off'
|
| 261 |
- app.encrypted_chats[account] = []
|
|
| 262 | 261 |
app.last_message_time[account] = {}
|
| 263 | 262 |
app.status_before_autoaway[account] = ''
|
| 264 |
- app.transport_avatar[account] = {}
|
|
| 265 | 263 |
app.gajim_optional_features[account] = []
|
| 266 | 264 |
app.caps_hash[account] = ''
|
| 267 | 265 |
helpers.update_optional_features(account)
|
| ... | ... | @@ -292,10 +290,8 @@ class AccountsWindow(Gtk.ApplicationWindow): |
| 292 | 290 |
del app.to_be_removed[account]
|
| 293 | 291 |
del app.newly_added[account]
|
| 294 | 292 |
del app.sleeper_state[account]
|
| 295 |
- del app.encrypted_chats[account]
|
|
| 296 | 293 |
del app.last_message_time[account]
|
| 297 | 294 |
del app.status_before_autoaway[account]
|
| 298 |
- del app.transport_avatar[account]
|
|
| 299 | 295 |
del app.gajim_optional_features[account]
|
| 300 | 296 |
del app.caps_hash[account]
|
| 301 | 297 |
if len(app.connections) >= 2:
|
| ... | ... | @@ -24,6 +24,9 @@ |
| 24 | 24 |
# You should have received a copy of the GNU General Public License
|
| 25 | 25 |
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
| 26 | 26 |
|
| 27 |
+from typing import Dict # pylint: disable=unused-import
|
|
| 28 |
+from typing import List # pylint: disable=unused-import
|
|
| 29 |
+ |
|
| 27 | 30 |
import os
|
| 28 | 31 |
import sys
|
| 29 | 32 |
import logging
|
| ... | ... | @@ -68,53 +71,66 @@ css_config = None |
| 68 | 71 |
|
| 69 | 72 |
os_info = None # used to cache os information
|
| 70 | 73 |
|
| 71 |
-transport_type = {} # list the type of transport
|
|
| 74 |
+transport_type = {} # type: Dict[str, str]
|
|
| 72 | 75 |
|
| 73 |
-last_message_time = {} # list of time of the latest incoming message
|
|
| 74 |
- # {acct1: {jid1: time1, jid2: time2}, }
|
|
| 75 |
-encrypted_chats = {} # list of encrypted chats {acct1: [jid1, jid2], ..}
|
|
| 76 |
+# dict of time of the latest incoming message per jid
|
|
| 77 |
+# {acct1: {jid1: time1, jid2: time2}, }
|
|
| 78 |
+last_message_time = {} # type: Dict[str, Dict[str, float]]
|
|
| 76 | 79 |
|
| 77 | 80 |
contacts = LegacyContactsAPI()
|
| 78 |
-gc_connected = {} # tell if we are connected to the room or not
|
|
| 79 |
- # {acct: {room_jid: True}}
|
|
| 80 |
-gc_passwords = {} # list of the pass required to enter a room
|
|
| 81 |
- # {room_jid: password}
|
|
| 82 |
-automatic_rooms = {} # list of rooms that must be automaticaly configured
|
|
| 83 |
- # and for which we have a list of invities
|
|
| 84 |
- #{account: {room_jid: {'invities': []}}}
|
|
| 85 |
- |
|
| 86 |
-groups = {} # list of groups
|
|
| 87 |
-newly_added = {} # list of contacts that has just signed in
|
|
| 88 |
-to_be_removed = {} # list of contacts that has just signed out
|
|
| 81 |
+ |
|
| 82 |
+# tell if we are connected to the room or not
|
|
| 83 |
+# {acct: {room_jid: True}}
|
|
| 84 |
+gc_connected = {} # type: Dict[str, Dict[str, bool]]
|
|
| 85 |
+ |
|
| 86 |
+# dict of the pass required to enter a room
|
|
| 87 |
+# {room_jid: password}
|
|
| 88 |
+gc_passwords = {} # type: Dict[str, str]
|
|
| 89 |
+ |
|
| 90 |
+# dict of rooms that must be automaticaly configured
|
|
| 91 |
+# and for which we have a list of invities
|
|
| 92 |
+# {account: {room_jid: {'invities': []}}}
|
|
| 93 |
+automatic_rooms = {} # type: Dict[str, Dict[str, Dict[str, List[str]]]]
|
|
| 94 |
+ |
|
| 95 |
+ # dict of groups, holds if they are expanded or not
|
|
| 96 |
+groups = {} # type: Dict[str, Dict[str, Dict[str, bool]]]
|
|
| 97 |
+ |
|
| 98 |
+# list of contacts that has just signed in
|
|
| 99 |
+newly_added = {} # type: Dict[str, List[str]]
|
|
| 100 |
+ |
|
| 101 |
+# list of contacts that has just signed out
|
|
| 102 |
+to_be_removed = {} # type: Dict[str, List[str]]
|
|
| 89 | 103 |
|
| 90 | 104 |
events = Events()
|
| 91 | 105 |
|
| 92 | 106 |
notification = None
|
| 93 | 107 |
|
| 94 |
-nicks = {} # list of our nick names in each account
|
|
| 108 |
+# list of our nick names in each account
|
|
| 109 |
+nicks = {} # type: Dict[str, str]
|
|
| 110 |
+ |
|
| 95 | 111 |
# should we block 'contact signed in' notifications for this account?
|
| 96 | 112 |
# this is only for the first 30 seconds after we change our show
|
| 97 | 113 |
# to something else than offline
|
| 98 | 114 |
# can also contain account/transport_jid to block notifications for contacts
|
| 99 | 115 |
# from this transport
|
| 100 | 116 |
block_signed_in_notifications = {}
|
| 101 |
-con_types = {} # type of each connection (ssl, tls, tcp, ...)
|
|
| 102 | 117 |
|
| 103 |
-sleeper_state = {} # whether we pass auto away / xa or not
|
|
| 118 |
+ # type of each connection (ssl, tls, tcp, ...)
|
|
| 119 |
+con_types = {} # type: Dict[str, Optional[str]]
|
|
| 120 |
+ |
|
| 121 |
+# whether we pass auto away / xa or not
|
|
| 104 | 122 |
#'off': don't use sleeper for this account
|
| 105 | 123 |
#'online': online and use sleeper
|
| 106 | 124 |
#'autoaway': autoaway and use sleeper
|
| 107 | 125 |
#'autoxa': autoxa and use sleeper
|
| 108 |
-status_before_autoaway = {}
|
|
| 126 |
+sleeper_state = {} # type: Dict[str, str]
|
|
| 109 | 127 |
|
| 110 |
-# jid of transport contacts for which we need to ask avatar when transport will
|
|
| 111 |
-# be online
|
|
| 112 |
-transport_avatar = {} # {transport_jid: [jid_list]}
|
|
| 128 |
+status_before_autoaway = {} # type: Dict[str, str]
|
|
| 113 | 129 |
|
| 114 | 130 |
# Is Gnome configured to activate on single click ?
|
| 115 | 131 |
single_click = False
|
| 116 | 132 |
SHOW_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd',
|
| 117 |
- 'invisible', 'error']
|
|
| 133 |
+ 'invisible', 'error']
|
|
| 118 | 134 |
|
| 119 | 135 |
# zeroconf account name
|
| 120 | 136 |
ZEROCONF_ACC_NAME = 'Local'
|
| ... | ... | @@ -32,6 +32,7 @@ if TYPE_CHECKING: |
| 32 | 32 |
from gajim.common.zeroconf.connection_zeroconf import ConnectionZeroconf
|
| 33 | 33 |
from gajim.common.contacts import Contact
|
| 34 | 34 |
from gajim.common.contacts import GC_Contact
|
| 35 |
+ from gajim.common.nec import NetworkEvent
|
|
| 35 | 36 |
|
| 36 | 37 |
ConnectionT = Union['Connection', 'ConnectionZeroconf']
|
| 37 | 38 |
ContactT = Union['Contact', 'GC_Contact']
|
| ... | ... | @@ -44,3 +45,9 @@ PEPHandlersDict = Dict[str, List[PEPNotifyCallback]] |
| 44 | 45 |
|
| 45 | 46 |
# Configpaths
|
| 46 | 47 |
PathTuple = Tuple[Optional[PathLocation], str, Optional[PathType]]
|
| 48 |
+ |
|
| 49 |
+# Plugins
|
|
| 50 |
+PluginExtensionPoints = Dict[str, Tuple[Optional[Callable[..., None]],
|
|
| 51 |
+ Optional[Callable[..., None]]]]
|
|
| 52 |
+EventHandlersDict = Dict[str, Tuple[int, Callable[['NetworkEvent'], Optional[bool]]]]
|
|
| 53 |
+PluginEvents = List['NetworkEvent']
|
| ... | ... | @@ -674,10 +674,8 @@ class RemoveAccountWindow: |
| 674 | 674 |
del app.to_be_removed[self.account]
|
| 675 | 675 |
del app.newly_added[self.account]
|
| 676 | 676 |
del app.sleeper_state[self.account]
|
| 677 |
- del app.encrypted_chats[self.account]
|
|
| 678 | 677 |
del app.last_message_time[self.account]
|
| 679 | 678 |
del app.status_before_autoaway[self.account]
|
| 680 |
- del app.transport_avatar[self.account]
|
|
| 681 | 679 |
del app.gajim_optional_features[self.account]
|
| 682 | 680 |
del app.caps_hash[self.account]
|
| 683 | 681 |
if len(app.connections) >= 2: # Do not merge accounts if only one exists
|
| ... | ... | @@ -582,10 +582,8 @@ class AccountCreationWizard: |
| 582 | 582 |
app.nicks[self.account] = config['name']
|
| 583 | 583 |
app.block_signed_in_notifications[self.account] = True
|
| 584 | 584 |
app.sleeper_state[self.account] = 'off'
|
| 585 |
- app.encrypted_chats[self.account] = []
|
|
| 586 | 585 |
app.last_message_time[self.account] = {}
|
| 587 | 586 |
app.status_before_autoaway[self.account] = ''
|
| 588 |
- app.transport_avatar[self.account] = {}
|
|
| 589 | 587 |
app.gajim_optional_features[self.account] = []
|
| 590 | 588 |
app.caps_hash[self.account] = ''
|
| 591 | 589 |
helpers.update_optional_features(self.account)
|
| 1 |
+# This file is part of Gajim.
|
|
| 2 |
+#
|
|
| 3 |
+# Gajim is free software; you can redistribute it and/or modify
|
|
| 4 |
+# it under the terms of the GNU General Public License as published
|
|
| 5 |
+# by the Free Software Foundation; version 3 only.
|
|
| 6 |
+#
|
|
| 7 |
+# Gajim is distributed in the hope that it will be useful,
|
|
| 8 |
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 9 |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
| 10 |
+# GNU General Public License for more details.
|
|
| 11 |
+#
|
|
| 12 |
+# You should have received a copy of the GNU General Public License
|
|
| 13 |
+# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
|
| 14 |
+ |
|
| 15 |
+# Constants for the gtk module
|
|
| 16 |
+ |
|
| 17 |
+from collections import namedtuple
|
|
| 18 |
+ |
|
| 19 |
+Filter = namedtuple('Filter', 'name pattern default')
|
| 1 |
+# This file is part of Gajim.
|
|
| 2 |
+#
|
|
| 3 |
+# Gajim is free software; you can redistribute it and/or modify
|
|
| 4 |
+# it under the terms of the GNU General Public License as published
|
|
| 5 |
+# by the Free Software Foundation; version 3 only.
|
|
| 6 |
+#
|
|
| 7 |
+# Gajim is distributed in the hope that it will be useful,
|
|
| 8 |
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 9 |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
| 10 |
+# GNU General Public License for more details.
|
|
| 11 |
+#
|
|
| 12 |
+# You should have received a copy of the GNU General Public License
|
|
| 13 |
+# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
|
| 14 |
+ |
|
| 1 | 15 |
import re
|
| 2 | 16 |
import weakref
|
| 3 | 17 |
from enum import IntEnum
|
| 1 |
-# Needs to be here because mypy get stuck on emoji_data.py
|
|
| 1 |
+# This file is part of Gajim.
|
|
| 2 |
+#
|
|
| 3 |
+# Gajim is free software; you can redistribute it and/or modify
|
|
| 4 |
+# it under the terms of the GNU General Public License as published
|
|
| 5 |
+# by the Free Software Foundation; version 3 only.
|
|
| 6 |
+#
|
|
| 7 |
+# Gajim is distributed in the hope that it will be useful,
|
|
| 8 |
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 9 |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
| 10 |
+# GNU General Public License for more details.
|
|
| 11 |
+#
|
|
| 12 |
+# You should have received a copy of the GNU General Public License
|
|
| 13 |
+# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
|
| 14 |
+ |
|
| 15 |
+from enum import IntEnum
|
|
| 16 |
+from collections import OrderedDict
|
|
| 17 |
+ |
|
| 18 |
+from gi.repository import GdkPixbuf
|
|
| 19 |
+ |
|
| 20 |
+class Emoji(IntEnum):
|
|
| 21 |
+ ...
|
|
| 22 |
+ |
|
| 23 |
+def is_emoji(codepoints: str) -> bool: ...
|
|
| 24 |
+def get_emoji_pixbuf(codepoints: str) -> GdkPixbuf.Pixbuf: ...
|
|
| 25 |
+ |
|
| 26 |
+class EmojiData(OrderedDict):
|
|
| 27 |
+ ...
|
|
| 28 |
+ |
|
| 29 |
+class EmojiPixbufs(dict):
|
|
| 30 |
+ ...
|
|
| 31 |
+ |
|
| 32 |
+class EmojiAsciiData(dict):
|
|
| 33 |
+ ...
|
|
| 34 |
+ |
|
| 35 |
+emoji_pixbufs = EmojiPixbufs()
|
|
| 36 |
+ |
|
| 37 |
+emoji_ascii_data = EmojiAsciiData()
|
|
| 38 |
+ |
|
| 39 |
+emoji_data = EmojiData()
|
| ... | ... | @@ -18,7 +18,6 @@ |
| 18 | 18 |
import os
|
| 19 | 19 |
import sys
|
| 20 | 20 |
from pathlib import Path
|
| 21 |
-from collections import namedtuple
|
|
| 22 | 21 |
|
| 23 | 22 |
from gi.repository import Gtk
|
| 24 | 23 |
from gi.repository import GdkPixbuf
|
| ... | ... | @@ -26,11 +25,11 @@ from gi.repository import GObject |
| 26 | 25 |
|
| 27 | 26 |
from gajim.common import app
|
| 28 | 27 |
from gajim.common.i18n import _
|
| 28 |
+from gajim.gtk.const import Filter
|
|
| 29 |
+from gajim.gtk.types import FilterList # pylint: disable=unused-import
|
|
| 29 | 30 |
|
| 30 |
-Filter = namedtuple('Filter', 'name pattern default')
|
|
| 31 | 31 |
|
| 32 |
- |
|
| 33 |
-def _require_native():
|
|
| 32 |
+def _require_native() -> bool:
|
|
| 34 | 33 |
if app.is_flatpak():
|
| 35 | 34 |
return True
|
| 36 | 35 |
if sys.platform in ('win32', 'darwin'):
|
| ... | ... | @@ -85,7 +84,7 @@ class BaseFileChooser: |
| 85 | 84 |
class BaseFileOpenDialog:
|
| 86 | 85 |
|
| 87 | 86 |
_title = _('Choose File to Send…')
|
| 88 |
- _filters = [Filter(_('All files'), '*', True)]
|
|
| 87 |
+ _filters = [Filter(_('All files'), '*', True)] # type: FilterList
|
|
| 89 | 88 |
|
| 90 | 89 |
|
| 91 | 90 |
class BaseAvatarChooserDialog:
|
| ... | ... | @@ -96,7 +95,7 @@ class BaseAvatarChooserDialog: |
| 96 | 95 |
if _require_native():
|
| 97 | 96 |
_filters = [Filter(_('PNG files'), '*.png', True),
|
| 98 | 97 |
Filter(_('JPEG files'), '*.jp*g', False),
|
| 99 |
- Filter(_('SVG files'), '*.svg', False)]
|
|
| 98 |
+ Filter(_('SVG files'), '*.svg', False)] # type: FilterList
|
|
| 100 | 99 |
else:
|
| 101 | 100 |
_filters = [Filter(_('Images'), ['image/png',
|
| 102 | 101 |
'image/jpeg',
|
| ... | ... | @@ -106,7 +105,7 @@ class BaseAvatarChooserDialog: |
| 106 | 105 |
class NativeFileChooserDialog(Gtk.FileChooserNative, BaseFileChooser):
|
| 107 | 106 |
|
| 108 | 107 |
_title = ''
|
| 109 |
- _filters = []
|
|
| 108 |
+ _filters = [] # type: FilterList
|
|
| 110 | 109 |
_action = Gtk.FileChooserAction.OPEN
|
| 111 | 110 |
|
| 112 | 111 |
def __init__(self, accept_cb, cancel_cb=None, transient_for=None,
|
| ... | ... | @@ -161,7 +160,7 @@ class NativeAvatarChooserDialog(BaseAvatarChooserDialog, NativeFileChooserDialog |
| 161 | 160 |
class GtkFileChooserDialog(Gtk.FileChooserDialog, BaseFileChooser):
|
| 162 | 161 |
|
| 163 | 162 |
_title = ''
|
| 164 |
- _filters = []
|
|
| 163 |
+ _filters = [] # type: FilterList
|
|
| 165 | 164 |
_action = Gtk.FileChooserAction.OPEN
|
| 166 | 165 |
_preivew_size = (200, 200)
|
| 167 | 166 |
|
| 1 |
+# This file is part of Gajim.
|
|
| 2 |
+#
|
|
| 3 |
+# Gajim is free software; you can redistribute it and/or modify
|
|
| 4 |
+# it under the terms of the GNU General Public License as published
|
|
| 5 |
+# by the Free Software Foundation; version 3 only.
|
|
| 6 |
+#
|
|
| 7 |
+# Gajim is distributed in the hope that it will be useful,
|
|
| 8 |
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 9 |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
| 10 |
+# GNU General Public License for more details.
|
|
| 11 |
+#
|
|
| 12 |
+# You should have received a copy of the GNU General Public License
|
|
| 13 |
+# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
|
| 14 |
+ |
|
| 15 |
+# Types for typechecking
|
|
| 16 |
+ |
|
| 17 |
+from typing import ClassVar
|
|
| 18 |
+from typing import List
|
|
| 19 |
+ |
|
| 20 |
+from gajim.gtk.const import Filter
|
|
| 21 |
+ |
|
| 22 |
+FilterList = ClassVar[List[Filter]]
|
| ... | ... | @@ -17,6 +17,8 @@ |
| 17 | 17 |
# You should have received a copy of the GNU General Public License
|
| 18 | 18 |
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
| 19 | 19 |
|
| 20 |
+from typing import cast
|
|
| 21 |
+ |
|
| 20 | 22 |
import sys
|
| 21 | 23 |
import os
|
| 22 | 24 |
import traceback
|
| ... | ... | @@ -40,7 +42,8 @@ if __name__ == '__main__': |
| 40 | 42 |
glade_file = os.path.join('data', 'gui', 'exception_dialog.ui')
|
| 41 | 43 |
else:
|
| 42 | 44 |
from gajim.common import configpaths
|
| 43 |
- glade_file = os.path.join(configpaths.get('GUI'), 'exception_dialog.ui')
|
|
| 45 |
+ gui_path = cast(str, configpaths.get('GUI'))
|
|
| 46 |
+ glade_file = os.path.join(gui_path, 'exception_dialog.ui')
|
|
| 44 | 47 |
|
| 45 | 48 |
|
| 46 | 49 |
_exception_in_progress = threading.Lock()
|
| ... | ... | @@ -2714,10 +2714,8 @@ class Interface: |
| 2714 | 2714 |
app.nicks[a] = app.config.get_per('accounts', a, 'name')
|
| 2715 | 2715 |
app.block_signed_in_notifications[a] = True
|
| 2716 | 2716 |
app.sleeper_state[a] = 0
|
| 2717 |
- app.encrypted_chats[a] = []
|
|
| 2718 | 2717 |
app.last_message_time[a] = {}
|
| 2719 | 2718 |
app.status_before_autoaway[a] = ''
|
| 2720 |
- app.transport_avatar[a] = {}
|
|
| 2721 | 2719 |
app.gajim_optional_features[a] = []
|
| 2722 | 2720 |
app.caps_hash[a] = ''
|
| 2723 | 2721 |
|
| ... | ... | @@ -44,10 +44,6 @@ from gi.repository import Gtk |
| 44 | 44 |
from gi.repository import Gdk
|
| 45 | 45 |
from gi.repository import GdkPixbuf
|
| 46 | 46 |
|
| 47 |
-if __name__ == '__main__':
|
|
| 48 |
- from gajim.common import configpaths
|
|
| 49 |
- configpaths.init()
|
|
| 50 |
- |
|
| 51 | 47 |
from gajim.common import app
|
| 52 | 48 |
from gajim.common import helpers
|
| 53 | 49 |
from gajim.common.i18n import _
|
| ... | ... | @@ -1086,185 +1082,3 @@ class HtmlTextView(Gtk.TextView): |
| 1086 | 1082 |
self.add_child_at_anchor(emoji, anchor)
|
| 1087 | 1083 |
buffer_.delete_mark(start_mark)
|
| 1088 | 1084 |
buffer_.delete_mark(end_mark)
|
| 1089 |
- |
|
| 1090 |
-change_cursor = None
|
|
| 1091 |
- |
|
| 1092 |
-if __name__ == '__main__':
|
|
| 1093 |
- from gajim.conversation_textview import ConversationTextview
|
|
| 1094 |
- from gajim.gui_interface import Interface
|
|
| 1095 |
- |
|
| 1096 |
- Interface()
|
|
| 1097 |
- |
|
| 1098 |
- # create fake app.plugin_manager.gui_extension_point method for tests
|
|
| 1099 |
- def extension_point(*args):
|
|
| 1100 |
- pass
|
|
| 1101 |
- def gui_extension_point(*args):
|
|
| 1102 |
- pass
|
|
| 1103 |
- app.plugin_manager = Interface()
|
|
| 1104 |
- app.plugin_manager.extension_point = extension_point
|
|
| 1105 |
- app.plugin_manager.gui_extension_point = gui_extension_point
|
|
| 1106 |
- |
|
| 1107 |
- htmlview = ConversationTextview(None)
|
|
| 1108 |
- |
|
| 1109 |
- def on_textview_motion_notify_event(widget, event):
|
|
| 1110 |
- """
|
|
| 1111 |
- Change the cursor to a hand when we are over a mail or an url
|
|
| 1112 |
- """
|
|
| 1113 |
- global change_cursor
|
|
| 1114 |
- w = htmlview.tv.get_window(Gtk.TextWindowType.TEXT)
|
|
| 1115 |
- device = w.get_display().get_device_manager().get_client_pointer()
|
|
| 1116 |
- pointer = w.get_device_position(device)
|
|
| 1117 |
- x = pointer[1]
|
|
| 1118 |
- y = pointer[2]
|
|
| 1119 |
- tags = htmlview.tv.get_iter_at_location(x, y)[1].get_tags()
|
|
| 1120 |
- if change_cursor:
|
|
| 1121 |
- w.set_cursor(get_cursor('XTERM'))
|
|
| 1122 |
- change_cursor = None
|
|
| 1123 |
- for tag in tags:
|
|
| 1124 |
- try:
|
|
| 1125 |
- if tag.is_anchor:
|
|
| 1126 |
- w.set_cursor(get_cursor('HAND2'))
|
|
| 1127 |
- change_cursor = tag
|
|
| 1128 |
- except Exception:
|
|
| 1129 |
- pass
|
|
| 1130 |
- |
|
| 1131 |
- htmlview.tv.connect('motion_notify_event', on_textview_motion_notify_event)
|
|
| 1132 |
- |
|
| 1133 |
- def handler(texttag, widget, event, iter_, kind):
|
|
| 1134 |
- if event.type == Gdk.EventType.BUTTON_PRESS:
|
|
| 1135 |
- pass
|
|
| 1136 |
- |
|
| 1137 |
- htmlview.tv.hyperlink_handler = htmlview.hyperlink_handler
|
|
| 1138 |
- |
|
| 1139 |
- htmlview.print_real_text(None, xhtml='<div>'
|
|
| 1140 |
- '<span style="color: red; text-decoration:underline">Hello</span><br/>\n'
|
|
| 1141 |
- ' <img src="http://images.slashdot.org/topics/topicsoftware.gif"/><br/>\n'
|
|
| 1142 |
- '<span style="font-size: 500%; font-family: serif">World</span>\n'
|
|
| 1143 |
- '</div>\n')
|
|
| 1144 |
- htmlview.print_real_text(None, xhtml='<hr />')
|
|
| 1145 |
- htmlview.print_real_text(None, xhtml='''
|
|
| 1146 |
- <body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 1147 |
- <p xmlns='http://www.w3.org/1999/xhtml'>a:b
|
|
| 1148 |
- <a href='http://google.com/' xmlns='http://www.w3.org/1999/xhtml'>Google
|
|
| 1149 |
- </a>
|
|
| 1150 |
- </p><br/>
|
|
| 1151 |
- </body>''')
|
|
| 1152 |
- htmlview.print_real_text(None, xhtml='''
|
|
| 1153 |
- <body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 1154 |
- <p style='font-size:large'>
|
|
| 1155 |
- <span style='font-style: italic'>O
|
|
| 1156 |
- <span style='font-size:larger'>M</span>G</span>,
|
|
| 1157 |
- I'm <span style='color:green'>green</span>
|
|
| 1158 |
- with <span style='font-weight: bold'>envy</span>!
|
|
| 1159 |
- </p>
|
|
| 1160 |
- </body>
|
|
| 1161 |
- ''')
|
|
| 1162 |
- htmlview.print_real_text(None, xhtml='<hr />')
|
|
| 1163 |
- htmlview.print_real_text(None, xhtml='''
|
|
| 1164 |
- <body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 1165 |
- http://test.com/ testing links autolinkifying
|
|
| 1166 |
- </body>
|
|
| 1167 |
- ''')
|
|
| 1168 |
- htmlview.print_real_text(None, xhtml='<hr />')
|
|
| 1169 |
- htmlview.print_real_text(None, xhtml='''
|
|
| 1170 |
- <body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 1171 |
- <p>As Emerson said in his essay <span style='
|
|
| 1172 |
- font-style: italic; background-color:cyan'>Self-Reliance</span>:</p>
|
|
| 1173 |
- <p style='margin-left: 5px; margin-right: 2%'>
|
|
| 1174 |
- "A foolish consistency is the hobgoblin of little minds."
|
|
| 1175 |
- </p>
|
|
| 1176 |
- </body>
|
|
| 1177 |
- ''')
|
|
| 1178 |
- htmlview.print_real_text(None, xhtml='<hr />')
|
|
| 1179 |
- htmlview.print_real_text(None, xhtml='''
|
|
| 1180 |
- <body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 1181 |
- <p style='text-align:center'>
|
|
| 1182 |
- Hey, are you licensed to <a href='http://www.jabber.org/'>Jabber</a>?
|
|
| 1183 |
- </p>
|
|
| 1184 |
- <p style='text-align:right'>
|
|
| 1185 |
- <img src='http://www.xmpp.org/images/psa-license.jpg'
|
|
| 1186 |
- alt='A License to Jabber' width='50%' height='50%'/>
|
|
| 1187 |
- </p>
|
|
| 1188 |
- </body>
|
|
| 1189 |
- ''')
|
|
| 1190 |
- htmlview.print_real_text(None, xhtml='<hr />')
|
|
| 1191 |
- htmlview.print_real_text(None, xhtml='''
|
|
| 1192 |
- <body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 1193 |
- <ul style='background-color:rgb(120,140,100)'>
|
|
| 1194 |
- <li> One </li>
|
|
| 1195 |
- <li> Two </li>
|
|
| 1196 |
- <li> Three </li>
|
|
| 1197 |
- </ul><hr /><pre style="background-color:rgb(120,120,120)">def fac(n):
|
|
| 1198 |
-def faciter(n,acc):
|
|
| 1199 |
- if n==0: return acc
|
|
| 1200 |
- return faciter(n-1, acc*n)
|
|
| 1201 |
-if n<0: raise ValueError('Must be non-negative')
|
|
| 1202 |
-return faciter(n,1)</pre>
|
|
| 1203 |
- </body>
|
|
| 1204 |
- ''')
|
|
| 1205 |
- htmlview.print_real_text(None, xhtml='<hr />')
|
|
| 1206 |
- htmlview.print_real_text(None, xhtml='''
|
|
| 1207 |
- <body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 1208 |
- <ol style='background-color:rgb(120,140,100)'>
|
|
| 1209 |
- <li> One </li>
|
|
| 1210 |
- <li> Two is nested: <ul style='background-color:rgb(200,200,100)'>
|
|
| 1211 |
- <li> One </li>
|
|
| 1212 |
- <li style='font-size:50%'> Two </li>
|
|
| 1213 |
- <li style='font-size:200%'> Three </li>
|
|
| 1214 |
- <li style='font-size:9999pt'> Four </li>
|
|
| 1215 |
- </ul></li>
|
|
| 1216 |
- <li> Three </li></ol>
|
|
| 1217 |
- </body>
|
|
| 1218 |
- ''')
|
|
| 1219 |
- htmlview.print_real_text(None, xhtml='<hr />')
|
|
| 1220 |
- htmlview.print_real_text(None, xhtml='''
|
|
| 1221 |
- <body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 1222 |
- <p>
|
|
| 1223 |
- <strong>
|
|
| 1224 |
- <a href='xmpp:example@example.org'>xmpp link</a>
|
|
| 1225 |
- </strong>: </p>
|
|
| 1226 |
- <div xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 1227 |
- <cite style='margin: 7px;' title='xmpp:examples@example.org'>
|
|
| 1228 |
- <p>
|
|
| 1229 |
- <strong>examples@example.org wrote:</strong>
|
|
| 1230 |
- </p>
|
|
| 1231 |
- <p>this cite - bla bla bla, smile- :-) …</p>
|
|
| 1232 |
- </cite>
|
|
| 1233 |
- <div>
|
|
| 1234 |
- <p>some text</p>
|
|
| 1235 |
- </div>
|
|
| 1236 |
- </div>
|
|
| 1237 |
- <p/>
|
|
| 1238 |
- <p>#232/1</p>
|
|
| 1239 |
- </body>
|
|
| 1240 |
- ''')
|
|
| 1241 |
- htmlview.print_real_text(None, xhtml='<hr />')
|
|
| 1242 |
- htmlview.print_real_text(None, xhtml='''
|
|
| 1243 |
- <body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 1244 |
- <br/>
|
|
| 1245 |
-<img src='data:image/png;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAw\
|
|
| 1246 |
-AAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFz\
|
|
| 1247 |
-ByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSp\
|
|
| 1248 |
-a/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJl\
|
|
| 1249 |
-ZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uis\
|
|
| 1250 |
-F81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PH\
|
|
| 1251 |
-hhx4dbgYKAAA7' alt='Larry'/>
|
|
| 1252 |
- </body>
|
|
| 1253 |
- ''')
|
|
| 1254 |
- htmlview.tv.show()
|
|
| 1255 |
- sw = Gtk.ScrolledWindow()
|
|
| 1256 |
- sw.set_property('hscrollbar-policy', Gtk.PolicyType.AUTOMATIC)
|
|
| 1257 |
- sw.set_property('vscrollbar-policy', Gtk.PolicyType.AUTOMATIC)
|
|
| 1258 |
- sw.set_property('border-width', 0)
|
|
| 1259 |
- sw.add(htmlview.tv)
|
|
| 1260 |
- sw.show()
|
|
| 1261 |
- frame = Gtk.Frame()
|
|
| 1262 |
- frame.set_shadow_type(Gtk.ShadowType.IN)
|
|
| 1263 |
- frame.show()
|
|
| 1264 |
- frame.add(sw)
|
|
| 1265 |
- win = Gtk.Window()
|
|
| 1266 |
- win.add(frame)
|
|
| 1267 |
- win.set_default_size(400, 300)
|
|
| 1268 |
- win.show_all()
|
|
| 1269 |
- win.connect('destroy', lambda win: Gtk.main_quit())
|
|
| 1270 |
- Gtk.main()
|
| ... | ... | @@ -21,15 +21,25 @@ Base class for implementing plugin. |
| 21 | 21 |
:license: GPL
|
| 22 | 22 |
'''
|
| 23 | 23 |
|
| 24 |
+from typing import List # pylint: disable=W0611
|
|
| 25 |
+from typing import Tuple # pylint: disable=W0611
|
|
| 26 |
+from typing import Dict # pylint: disable=W0611
|
|
| 27 |
+from typing import Any # pylint: disable=W0611
|
|
| 28 |
+ |
|
| 24 | 29 |
import os
|
| 25 | 30 |
import locale
|
| 31 |
+import logging
|
|
| 32 |
+import pickle
|
|
| 26 | 33 |
|
| 27 | 34 |
from gajim.common import configpaths
|
| 35 |
+from gajim.common.types import PluginExtensionPoints # pylint: disable=W0611
|
|
| 36 |
+from gajim.common.types import EventHandlersDict # pylint: disable=W0611
|
|
| 37 |
+from gajim.common.types import PluginEvents # pylint: disable=W0611
|
|
| 28 | 38 |
|
| 29 | 39 |
from gajim.plugins.helpers import log_calls, log
|
| 30 | 40 |
from gajim.plugins.gui import GajimPluginConfigDialog
|
| 31 | 41 |
|
| 32 |
-import logging
|
|
| 42 |
+ |
|
| 33 | 43 |
log = logging.getLogger('gajim.p.plugin')
|
| 34 | 44 |
|
| 35 | 45 |
|
| ... | ... | @@ -86,7 +96,7 @@ class GajimPlugin: |
| 86 | 96 |
|
| 87 | 97 |
:todo: should be allow rich text here (like HTML or reStructuredText)?
|
| 88 | 98 |
'''
|
| 89 |
- authors = []
|
|
| 99 |
+ authors = [] # type: List[str]
|
|
| 90 | 100 |
'''
|
| 91 | 101 |
Plugin authors.
|
| 92 | 102 |
|
| ... | ... | @@ -104,7 +114,7 @@ class GajimPlugin: |
| 104 | 114 |
:todo: should we check whether provided string is valid URI? (Maybe
|
| 105 | 115 |
using 'property')
|
| 106 | 116 |
'''
|
| 107 |
- gui_extension_points = {}
|
|
| 117 |
+ gui_extension_points = {} # type: PluginExtensionPoints
|
|
| 108 | 118 |
'''
|
| 109 | 119 |
Extension points that plugin wants to connect with and handlers to be used.
|
| 110 | 120 |
|
| ... | ... | @@ -118,7 +128,7 @@ class GajimPlugin: |
| 118 | 128 |
or when extpoint is destroyed and plugin is activate (eg. chat window
|
| 119 | 129 |
closed).
|
| 120 | 130 |
'''
|
| 121 |
- config_default_values = {}
|
|
| 131 |
+ config_default_values = {} # type: Dict[str, Tuple[Any, str]]
|
|
| 122 | 132 |
'''
|
| 123 | 133 |
Default values for keys that should be stored in plug-in config.
|
| 124 | 134 |
|
| ... | ... | @@ -132,7 +142,7 @@ class GajimPlugin: |
| 132 | 142 |
|
| 133 | 143 |
:type: {} of 2-element tuples
|
| 134 | 144 |
'''
|
| 135 |
- events_handlers = {}
|
|
| 145 |
+ events_handlers = {} # type: EventHandlersDict
|
|
| 136 | 146 |
'''
|
| 137 | 147 |
Dictionary with events handlers.
|
| 138 | 148 |
|
| ... | ... | @@ -143,7 +153,7 @@ class GajimPlugin: |
| 143 | 153 |
|
| 144 | 154 |
:type: {} with 2-element tuples
|
| 145 | 155 |
'''
|
| 146 |
- events = []
|
|
| 156 |
+ events = [] # type: PluginEvents
|
|
| 147 | 157 |
'''
|
| 148 | 158 |
New network event classes to be registered in Network Events Controller.
|
| 149 | 159 |
|
| ... | ... | @@ -152,7 +162,7 @@ class GajimPlugin: |
| 152 | 162 |
'''
|
| 153 | 163 |
|
| 154 | 164 |
@log_calls('GajimPlugin')
|
| 155 |
- def __init__(self):
|
|
| 165 |
+ def __init__(self) -> None:
|
|
| 156 | 166 |
self.config = GajimPluginConfig(self)
|
| 157 | 167 |
'''
|
| 158 | 168 |
Plug-in configuration dictionary.
|
| ... | ... | @@ -168,11 +178,11 @@ class GajimPlugin: |
| 168 | 178 |
self.init()
|
| 169 | 179 |
|
| 170 | 180 |
@log_calls('GajimPlugin')
|
| 171 |
- def save_config(self):
|
|
| 181 |
+ def save_config(self) -> None:
|
|
| 172 | 182 |
self.config.save()
|
| 173 | 183 |
|
| 174 | 184 |
@log_calls('GajimPlugin')
|
| 175 |
- def load_config(self):
|
|
| 185 |
+ def load_config(self) -> None:
|
|
| 176 | 186 |
self.config.load()
|
| 177 | 187 |
|
| 178 | 188 |
def __eq__(self, plugin):
|
| ... | ... | @@ -203,7 +213,6 @@ class GajimPlugin: |
| 203 | 213 |
def deactivate(self):
|
| 204 | 214 |
pass
|
| 205 | 215 |
|
| 206 |
-import pickle
|
|
| 207 | 216 |
|
| 208 | 217 |
class GajimPluginConfig():
|
| 209 | 218 |
@log_calls('GajimPluginConfig')
|
| 1 |
+import sys
|
|
| 2 |
+import os
|
|
| 3 |
+from unittest.mock import MagicMock
|
|
| 4 |
+ |
|
| 5 |
+sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
|
|
| 6 |
+ |
|
| 7 |
+from gi.repository import Gtk, Gdk
|
|
| 8 |
+ |
|
| 9 |
+from gajim.common import app
|
|
| 10 |
+from gajim.common import configpaths
|
|
| 11 |
+configpaths.init()
|
|
| 12 |
+from gajim.common import caps_cache
|
|
| 13 |
+ |
|
| 14 |
+from gajim.gtk.util import get_cursor
|
|
| 15 |
+from gajim.conversation_textview import ConversationTextview
|
|
| 16 |
+from gajim.gui_interface import Interface
|
|
| 17 |
+ |
|
| 18 |
+ |
|
| 19 |
+caps_cache.capscache = MagicMock()
|
|
| 20 |
+app.plugin_manager = MagicMock()
|
|
| 21 |
+app.logger = MagicMock()
|
|
| 22 |
+app.interface = Interface()
|
|
| 23 |
+ |
|
| 24 |
+change_cursor = None
|
|
| 25 |
+htmlview = ConversationTextview(None)
|
|
| 26 |
+ |
|
| 27 |
+def on_textview_motion_notify_event(widget, event):
|
|
| 28 |
+ """
|
|
| 29 |
+ Change the cursor to a hand when we are over a mail or an url
|
|
| 30 |
+ """
|
|
| 31 |
+ global change_cursor
|
|
| 32 |
+ w = htmlview.tv.get_window(Gtk.TextWindowType.TEXT)
|
|
| 33 |
+ device = w.get_display().get_device_manager().get_client_pointer()
|
|
| 34 |
+ pointer = w.get_device_position(device)
|
|
| 35 |
+ x = pointer[1]
|
|
| 36 |
+ y = pointer[2]
|
|
| 37 |
+ tags = htmlview.tv.get_iter_at_location(x, y)[1].get_tags()
|
|
| 38 |
+ if change_cursor:
|
|
| 39 |
+ w.set_cursor(get_cursor('XTERM'))
|
|
| 40 |
+ change_cursor = None
|
|
| 41 |
+ for tag in tags:
|
|
| 42 |
+ try:
|
|
| 43 |
+ if tag.is_anchor:
|
|
| 44 |
+ w.set_cursor(get_cursor('HAND2'))
|
|
| 45 |
+ change_cursor = tag
|
|
| 46 |
+ except Exception:
|
|
| 47 |
+ pass
|
|
| 48 |
+ |
|
| 49 |
+htmlview.tv.connect('motion_notify_event', on_textview_motion_notify_event)
|
|
| 50 |
+ |
|
| 51 |
+def handler(texttag, widget, event, iter_, kind):
|
|
| 52 |
+ if event.type == Gdk.EventType.BUTTON_PRESS:
|
|
| 53 |
+ pass
|
|
| 54 |
+ |
|
| 55 |
+htmlview.tv.hyperlink_handler = htmlview.hyperlink_handler
|
|
| 56 |
+ |
|
| 57 |
+htmlview.print_real_text(None, xhtml='<div>'
|
|
| 58 |
+'<span style="color: red; text-decoration:underline">Hello</span><br/>\n'
|
|
| 59 |
+ ' <img src="http://images.slashdot.org/topics/topicsoftware.gif"/><br/>\n'
|
|
| 60 |
+'<span style="font-size: 500%; font-family: serif">World</span>\n'
|
|
| 61 |
+ '</div>\n')
|
|
| 62 |
+htmlview.print_real_text(None, xhtml='<hr />')
|
|
| 63 |
+htmlview.print_real_text(None, xhtml='''
|
|
| 64 |
+<body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 65 |
+ <p xmlns='http://www.w3.org/1999/xhtml'>a:b
|
|
| 66 |
+ <a href='http://google.com/' xmlns='http://www.w3.org/1999/xhtml'>Google
|
|
| 67 |
+ </a>
|
|
| 68 |
+ </p><br/>
|
|
| 69 |
+</body>''')
|
|
| 70 |
+htmlview.print_real_text(None, xhtml='''
|
|
| 71 |
+ <body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 72 |
+ <p style='font-size:large'>
|
|
| 73 |
+ <span style='font-style: italic'>O
|
|
| 74 |
+ <span style='font-size:larger'>M</span>G</span>,
|
|
| 75 |
+ I'm <span style='color:green'>green</span>
|
|
| 76 |
+ with <span style='font-weight: bold'>envy</span>!
|
|
| 77 |
+ </p>
|
|
| 78 |
+ </body>
|
|
| 79 |
+ ''')
|
|
| 80 |
+htmlview.print_real_text(None, xhtml='<hr />')
|
|
| 81 |
+htmlview.print_real_text(None, xhtml='''
|
|
| 82 |
+<body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 83 |
+ http://test.com/ testing links autolinkifying
|
|
| 84 |
+</body>
|
|
| 85 |
+ ''')
|
|
| 86 |
+htmlview.print_real_text(None, xhtml='<hr />')
|
|
| 87 |
+htmlview.print_real_text(None, xhtml='''
|
|
| 88 |
+<body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 89 |
+ <p>As Emerson said in his essay <span style='
|
|
| 90 |
+ font-style: italic; background-color:cyan'>Self-Reliance</span>:</p>
|
|
| 91 |
+ <p style='margin-left: 5px; margin-right: 2%'>
|
|
| 92 |
+ "A foolish consistency is the hobgoblin of little minds."
|
|
| 93 |
+ </p>
|
|
| 94 |
+</body>
|
|
| 95 |
+ ''')
|
|
| 96 |
+htmlview.print_real_text(None, xhtml='<hr />')
|
|
| 97 |
+htmlview.print_real_text(None, xhtml='''
|
|
| 98 |
+<body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 99 |
+ <p style='text-align:center'>
|
|
| 100 |
+ Hey, are you licensed to <a href='http://www.jabber.org/'>Jabber</a>?
|
|
| 101 |
+ </p>
|
|
| 102 |
+ <p style='text-align:right'>
|
|
| 103 |
+ <img src='http://www.xmpp.org/images/psa-license.jpg'
|
|
| 104 |
+ alt='A License to Jabber' width='50%' height='50%'/>
|
|
| 105 |
+ </p>
|
|
| 106 |
+</body>
|
|
| 107 |
+ ''')
|
|
| 108 |
+htmlview.print_real_text(None, xhtml='<hr />')
|
|
| 109 |
+htmlview.print_real_text(None, xhtml='''
|
|
| 110 |
+<body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 111 |
+ <ul style='background-color:rgb(120,140,100)'>
|
|
| 112 |
+ <li> One </li>
|
|
| 113 |
+ <li> Two </li>
|
|
| 114 |
+ <li> Three </li>
|
|
| 115 |
+ </ul><hr /><pre style="background-color:rgb(120,120,120)">def fac(n):
|
|
| 116 |
+def faciter(n,acc):
|
|
| 117 |
+if n==0: return acc
|
|
| 118 |
+return faciter(n-1, acc*n)
|
|
| 119 |
+if n<0: raise ValueError('Must be non-negative')
|
|
| 120 |
+return faciter(n,1)</pre>
|
|
| 121 |
+</body>
|
|
| 122 |
+ ''')
|
|
| 123 |
+htmlview.print_real_text(None, xhtml='<hr />')
|
|
| 124 |
+htmlview.print_real_text(None, xhtml='''
|
|
| 125 |
+<body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 126 |
+ <ol style='background-color:rgb(120,140,100)'>
|
|
| 127 |
+ <li> One </li>
|
|
| 128 |
+ <li> Two is nested: <ul style='background-color:rgb(200,200,100)'>
|
|
| 129 |
+ <li> One </li>
|
|
| 130 |
+ <li style='font-size:50%'> Two </li>
|
|
| 131 |
+ <li style='font-size:200%'> Three </li>
|
|
| 132 |
+ <li style='font-size:9999pt'> Four </li>
|
|
| 133 |
+ </ul></li>
|
|
| 134 |
+ <li> Three </li></ol>
|
|
| 135 |
+</body>
|
|
| 136 |
+ ''')
|
|
| 137 |
+htmlview.print_real_text(None, xhtml='<hr />')
|
|
| 138 |
+htmlview.print_real_text(None, xhtml='''
|
|
| 139 |
+<body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 140 |
+<p>
|
|
| 141 |
+ <strong>
|
|
| 142 |
+ <a href='xmpp:example@example.org'>xmpp link</a>
|
|
| 143 |
+ </strong>: </p>
|
|
| 144 |
+<div xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 145 |
+ <cite style='margin: 7px;' title='xmpp:examples@example.org'>
|
|
| 146 |
+ <p>
|
|
| 147 |
+ <strong>examples@example.org wrote:</strong>
|
|
| 148 |
+ </p>
|
|
| 149 |
+ <p>this cite - bla bla bla, smile- :-) …</p>
|
|
| 150 |
+ </cite>
|
|
| 151 |
+ <div>
|
|
| 152 |
+ <p>some text</p>
|
|
| 153 |
+ </div>
|
|
| 154 |
+</div>
|
|
| 155 |
+<p/>
|
|
| 156 |
+<p>#232/1</p>
|
|
| 157 |
+</body>
|
|
| 158 |
+''')
|
|
| 159 |
+htmlview.print_real_text(None, xhtml='<hr />')
|
|
| 160 |
+htmlview.print_real_text(None, xhtml='''
|
|
| 161 |
+<body xmlns='http://www.w3.org/1999/xhtml'>
|
|
| 162 |
+<br/>
|
|
| 163 |
+<img src='data:image/png;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAw\
|
|
| 164 |
+AAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFz\
|
|
| 165 |
+ByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSp\
|
|
| 166 |
+a/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJl\
|
|
| 167 |
+ZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uis\
|
|
| 168 |
+F81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PH\
|
|
| 169 |
+hhx4dbgYKAAA7' alt='Larry'/>
|
|
| 170 |
+</body>
|
|
| 171 |
+''')
|
|
| 172 |
+htmlview.tv.show()
|
|
| 173 |
+sw = Gtk.ScrolledWindow()
|
|
| 174 |
+sw.set_property('hscrollbar-policy', Gtk.PolicyType.AUTOMATIC)
|
|
| 175 |
+sw.set_property('vscrollbar-policy', Gtk.PolicyType.AUTOMATIC)
|
|
| 176 |
+sw.set_property('border-width', 0)
|
|
| 177 |
+sw.add(htmlview.tv)
|
|
| 178 |
+sw.show()
|
|
| 179 |
+frame = Gtk.Frame()
|
|
| 180 |
+frame.set_shadow_type(Gtk.ShadowType.IN)
|
|
| 181 |
+frame.show()
|
|
| 182 |
+frame.add(sw)
|
|
| 183 |
+win = Gtk.Window()
|
|
| 184 |
+win.add(frame)
|
|
| 185 |
+win.set_default_size(400, 300)
|
|
| 186 |
+win.show_all()
|
|
| 187 |
+win.connect('destroy', lambda win: Gtk.main_quit())
|
|
| 188 |
+Gtk.main()
|
| ... | ... | @@ -35,10 +35,8 @@ class MockConnection(Mock, ConnectionHandlers): |
| 35 | 35 |
app.nicks[account] = app.config.get_per('accounts', account, 'name')
|
| 36 | 36 |
app.block_signed_in_notifications[account] = True
|
| 37 | 37 |
app.sleeper_state[account] = 0
|
| 38 |
- app.encrypted_chats[account] = []
|
|
| 39 | 38 |
app.last_message_time[account] = {}
|
| 40 | 39 |
app.status_before_autoaway[account] = ''
|
| 41 |
- app.transport_avatar[account] = {}
|
|
| 42 | 40 |
app.gajim_optional_features[account] = []
|
| 43 | 41 |
app.caps_hash[account] = ''
|
| 44 | 42 |
|