Daniel Brötzmann pushed to branch mainwindow at gajim / gajim
Commits:
-
e55803ca
by wurstsalat at 2021-08-31T20:11:47+02:00
-
6cafceaa
by wurstsalat at 2021-08-31T20:14:36+02:00
-
f31a04ca
by wurstsalat at 2021-08-31T20:33:21+02:00
-
b5e487f4
by wurstsalat at 2021-09-02T22:38:00+02:00
-
a1e80261
by wurstsalat at 2021-09-02T23:23:47+02:00
-
2038a0d9
by wurstsalat at 2021-09-02T23:25:05+02:00
-
57340dec
by wurstsalat at 2021-09-02T23:26:05+02:00
13 changed files:
- gajim/common/jingle_ft.py
- gajim/common/jingle_session.py
- gajim/common/modules/jingle.py
- + gajim/data/gui/file_transfer_send.ui
- − gajim/data/gui/filetransfers_send_file_dialog.ui
- gajim/data/style/gajim.css
- gajim/gtk/call_widget.py
- gajim/gtk/controls/chat.py
- + gajim/gtk/file_transfer_send.py
- gajim/gtk/filetransfer.py
- + gajim/gtk/resource_selector.py
- gajim/gtk/tooltips.py
- gajim/gui_interface.py
Changes:
| ... | ... | @@ -101,13 +101,6 @@ def __init__(self, session, transport=None, file_props=None, |
| 101 | 101 |
self.session = session
|
| 102 | 102 |
self.media = 'file'
|
| 103 | 103 |
self.nominated_cand = {}
|
| 104 |
- if app.contacts.is_gc_contact(session.connection.name,
|
|
| 105 |
- session.peerjid):
|
|
| 106 |
- roomjid = session.peerjid.split('/')[0]
|
|
| 107 |
- dstaddr = hashlib.sha1(('%s%s%s' % (self.file_props.sid,
|
|
| 108 |
- session.ourjid, roomjid))
|
|
| 109 |
- .encode('utf-8')).hexdigest()
|
|
| 110 |
- self.file_props.dstaddr = dstaddr
|
|
| 111 | 104 |
self.state = State.NOT_STARTED
|
| 112 | 105 |
self.states = {
|
| 113 | 106 |
State.INITIALIZED : StateInitialized(self),
|
| ... | ... | @@ -516,7 +516,17 @@ def __on_session_initiate(self, stanza, jingle, error, action): |
| 516 | 516 |
"""
|
| 517 | 517 |
if self.state != JingleStates.ENDED:
|
| 518 | 518 |
raise OutOfOrder
|
| 519 |
- self.initiator = jingle['initiator']
|
|
| 519 |
+ |
|
| 520 |
+ # In "session-initiate", the <jingle/> element SHOULD possess an
|
|
| 521 |
+ # 'initiator' attribute. If it differs from the JID 'from', jingle
|
|
| 522 |
+ # 'initiator' SHOULD be ignored.
|
|
| 523 |
+ if jingle['initiator'] is None:
|
|
| 524 |
+ self.initiator = stanza['from']
|
|
| 525 |
+ elif jingle['initiator'] != stanza['from']:
|
|
| 526 |
+ self.initiator = stanza['from']
|
|
| 527 |
+ else:
|
|
| 528 |
+ self.initiator = jingle['initiator']
|
|
| 529 |
+ |
|
| 520 | 530 |
self.responder = self.ourjid
|
| 521 | 531 |
self.peerjid = self.initiator
|
| 522 | 532 |
self.accepted = False # user did not accept this session yet
|
| ... | ... | @@ -207,16 +207,7 @@ def start_audio_video(self, jid): |
| 207 | 207 |
|
| 208 | 208 |
def start_file_transfer(self, jid, file_props, request=False):
|
| 209 | 209 |
logger.info("start file transfer with file: %s", file_props)
|
| 210 |
- contact = app.contacts.get_contact_with_highest_priority(
|
|
| 211 |
- self._account, app.get_jid_without_resource(jid))
|
|
| 212 |
- if app.contacts.is_gc_contact(self._account, jid):
|
|
| 213 |
- gcc = jid.split('/')
|
|
| 214 |
- if len(gcc) == 2:
|
|
| 215 |
- contact = app.contacts.get_gc_contact(self._account,
|
|
| 216 |
- gcc[0],
|
|
| 217 |
- gcc[1])
|
|
| 218 |
- if contact is None:
|
|
| 219 |
- return None
|
|
| 210 |
+ contact = self._con.get_module('Contacts').get_contact(jid)
|
|
| 220 | 211 |
use_security = contact.supports(Namespace.JINGLE_XTLS)
|
| 221 | 212 |
jingle = JingleSession(self._con,
|
| 222 | 213 |
weinitiate=True,
|
| 1 |
+<?xml version="1.0" encoding="UTF-8"?>
|
|
| 2 |
+<!-- Generated with glade 3.38.2 -->
|
|
| 3 |
+<interface>
|
|
| 4 |
+ <requires lib="gtk+" version="3.24"/>
|
|
| 5 |
+ <object class="GtkStack" id="send_stack">
|
|
| 6 |
+ <property name="visible">True</property>
|
|
| 7 |
+ <property name="can-focus">False</property>
|
|
| 8 |
+ <property name="transition-type">slide-left-right</property>
|
|
| 9 |
+ <child>
|
|
| 10 |
+ <object class="GtkBox">
|
|
| 11 |
+ <property name="visible">True</property>
|
|
| 12 |
+ <property name="can-focus">False</property>
|
|
| 13 |
+ <property name="border-width">18</property>
|
|
| 14 |
+ <property name="orientation">vertical</property>
|
|
| 15 |
+ <property name="spacing">6</property>
|
|
| 16 |
+ <child>
|
|
| 17 |
+ <object class="GtkLabel">
|
|
| 18 |
+ <property name="visible">True</property>
|
|
| 19 |
+ <property name="can-focus">False</property>
|
|
| 20 |
+ <property name="label" translatable="yes">Files to send</property>
|
|
| 21 |
+ <property name="xalign">0</property>
|
|
| 22 |
+ <style>
|
|
| 23 |
+ <class name="dim-label"/>
|
|
| 24 |
+ </style>
|
|
| 25 |
+ </object>
|
|
| 26 |
+ <packing>
|
|
| 27 |
+ <property name="expand">False</property>
|
|
| 28 |
+ <property name="fill">True</property>
|
|
| 29 |
+ <property name="position">1</property>
|
|
| 30 |
+ </packing>
|
|
| 31 |
+ </child>
|
|
| 32 |
+ <child>
|
|
| 33 |
+ <object class="GtkBox">
|
|
| 34 |
+ <property name="visible">True</property>
|
|
| 35 |
+ <property name="can-focus">False</property>
|
|
| 36 |
+ <property name="hexpand">True</property>
|
|
| 37 |
+ <property name="vexpand">True</property>
|
|
| 38 |
+ <property name="orientation">vertical</property>
|
|
| 39 |
+ <child>
|
|
| 40 |
+ <object class="GtkScrolledWindow">
|
|
| 41 |
+ <property name="visible">True</property>
|
|
| 42 |
+ <property name="can-focus">True</property>
|
|
| 43 |
+ <property name="hscrollbar-policy">never</property>
|
|
| 44 |
+ <property name="shadow-type">in</property>
|
|
| 45 |
+ <child>
|
|
| 46 |
+ <object class="GtkViewport">
|
|
| 47 |
+ <property name="visible">True</property>
|
|
| 48 |
+ <property name="can-focus">False</property>
|
|
| 49 |
+ <child>
|
|
| 50 |
+ <object class="GtkListBox" id="listbox">
|
|
| 51 |
+ <property name="visible">True</property>
|
|
| 52 |
+ <property name="can-focus">False</property>
|
|
| 53 |
+ <property name="vexpand">True</property>
|
|
| 54 |
+ <property name="selection-mode">multiple</property>
|
|
| 55 |
+ <property name="activate-on-single-click">False</property>
|
|
| 56 |
+ <signal name="add" handler="_on_files_changed" swapped="no"/>
|
|
| 57 |
+ <signal name="remove" handler="_on_files_changed" swapped="no"/>
|
|
| 58 |
+ </object>
|
|
| 59 |
+ </child>
|
|
| 60 |
+ </object>
|
|
| 61 |
+ </child>
|
|
| 62 |
+ </object>
|
|
| 63 |
+ <packing>
|
|
| 64 |
+ <property name="expand">True</property>
|
|
| 65 |
+ <property name="fill">True</property>
|
|
| 66 |
+ <property name="position">0</property>
|
|
| 67 |
+ </packing>
|
|
| 68 |
+ </child>
|
|
| 69 |
+ <child>
|
|
| 70 |
+ <object class="GtkToolbar">
|
|
| 71 |
+ <property name="visible">True</property>
|
|
| 72 |
+ <property name="can-focus">False</property>
|
|
| 73 |
+ <property name="show-arrow">False</property>
|
|
| 74 |
+ <property name="icon_size">1</property>
|
|
| 75 |
+ <child>
|
|
| 76 |
+ <object class="GtkToolButton">
|
|
| 77 |
+ <property name="visible">True</property>
|
|
| 78 |
+ <property name="can-focus">False</property>
|
|
| 79 |
+ <property name="tooltip-text" translatable="yes">Add Files</property>
|
|
| 80 |
+ <property name="use-underline">True</property>
|
|
| 81 |
+ <property name="icon-name">list-add-symbolic</property>
|
|
| 82 |
+ <signal name="clicked" handler="_select_files" swapped="no"/>
|
|
| 83 |
+ </object>
|
|
| 84 |
+ <packing>
|
|
| 85 |
+ <property name="expand">False</property>
|
|
| 86 |
+ <property name="homogeneous">False</property>
|
|
| 87 |
+ </packing>
|
|
| 88 |
+ </child>
|
|
| 89 |
+ <child>
|
|
| 90 |
+ <object class="GtkToolButton">
|
|
| 91 |
+ <property name="visible">True</property>
|
|
| 92 |
+ <property name="can-focus">False</property>
|
|
| 93 |
+ <property name="tooltip-text" translatable="yes">Remove Files</property>
|
|
| 94 |
+ <property name="use-underline">True</property>
|
|
| 95 |
+ <property name="icon-name">list-remove-symbolic</property>
|
|
| 96 |
+ <signal name="clicked" handler="_remove_files" swapped="no"/>
|
|
| 97 |
+ </object>
|
|
| 98 |
+ <packing>
|
|
| 99 |
+ <property name="expand">False</property>
|
|
| 100 |
+ <property name="homogeneous">True</property>
|
|
| 101 |
+ </packing>
|
|
| 102 |
+ </child>
|
|
| 103 |
+ <style>
|
|
| 104 |
+ <class name="inline-toolbar"/>
|
|
| 105 |
+ </style>
|
|
| 106 |
+ </object>
|
|
| 107 |
+ <packing>
|
|
| 108 |
+ <property name="expand">False</property>
|
|
| 109 |
+ <property name="fill">True</property>
|
|
| 110 |
+ <property name="position">1</property>
|
|
| 111 |
+ </packing>
|
|
| 112 |
+ </child>
|
|
| 113 |
+ </object>
|
|
| 114 |
+ <packing>
|
|
| 115 |
+ <property name="expand">False</property>
|
|
| 116 |
+ <property name="fill">True</property>
|
|
| 117 |
+ <property name="position">2</property>
|
|
| 118 |
+ </packing>
|
|
| 119 |
+ </child>
|
|
| 120 |
+ <child>
|
|
| 121 |
+ <object class="GtkLabel">
|
|
| 122 |
+ <property name="visible">True</property>
|
|
| 123 |
+ <property name="can-focus">False</property>
|
|
| 124 |
+ <property name="label" translatable="yes">Description</property>
|
|
| 125 |
+ <property name="xalign">0</property>
|
|
| 126 |
+ <style>
|
|
| 127 |
+ <class name="dim-label"/>
|
|
| 128 |
+ </style>
|
|
| 129 |
+ </object>
|
|
| 130 |
+ <packing>
|
|
| 131 |
+ <property name="expand">False</property>
|
|
| 132 |
+ <property name="fill">True</property>
|
|
| 133 |
+ <property name="position">3</property>
|
|
| 134 |
+ </packing>
|
|
| 135 |
+ </child>
|
|
| 136 |
+ <child>
|
|
| 137 |
+ <object class="GtkScrolledWindow">
|
|
| 138 |
+ <property name="height-request">70</property>
|
|
| 139 |
+ <property name="visible">True</property>
|
|
| 140 |
+ <property name="can-focus">True</property>
|
|
| 141 |
+ <property name="hscrollbar-policy">never</property>
|
|
| 142 |
+ <property name="shadow-type">in</property>
|
|
| 143 |
+ <child>
|
|
| 144 |
+ <object class="GtkTextView" id="description">
|
|
| 145 |
+ <property name="visible">True</property>
|
|
| 146 |
+ <property name="can-focus">True</property>
|
|
| 147 |
+ <property name="wrap-mode">word-char</property>
|
|
| 148 |
+ <property name="left-margin">6</property>
|
|
| 149 |
+ <property name="right-margin">6</property>
|
|
| 150 |
+ <property name="top-margin">6</property>
|
|
| 151 |
+ <property name="bottom-margin">6</property>
|
|
| 152 |
+ </object>
|
|
| 153 |
+ </child>
|
|
| 154 |
+ </object>
|
|
| 155 |
+ <packing>
|
|
| 156 |
+ <property name="expand">False</property>
|
|
| 157 |
+ <property name="fill">True</property>
|
|
| 158 |
+ <property name="position">4</property>
|
|
| 159 |
+ </packing>
|
|
| 160 |
+ </child>
|
|
| 161 |
+ <child>
|
|
| 162 |
+ <object class="GtkButton" id="files_send">
|
|
| 163 |
+ <property name="label" translatable="yes">_Send Files</property>
|
|
| 164 |
+ <property name="visible">True</property>
|
|
| 165 |
+ <property name="sensitive">False</property>
|
|
| 166 |
+ <property name="can-focus">True</property>
|
|
| 167 |
+ <property name="receives-default">True</property>
|
|
| 168 |
+ <property name="halign">center</property>
|
|
| 169 |
+ <property name="use-underline">True</property>
|
|
| 170 |
+ <signal name="clicked" handler="_on_send_clicked" swapped="no"/>
|
|
| 171 |
+ <style>
|
|
| 172 |
+ <class name="suggested-action"/>
|
|
| 173 |
+ </style>
|
|
| 174 |
+ </object>
|
|
| 175 |
+ <packing>
|
|
| 176 |
+ <property name="expand">False</property>
|
|
| 177 |
+ <property name="fill">True</property>
|
|
| 178 |
+ <property name="position">5</property>
|
|
| 179 |
+ </packing>
|
|
| 180 |
+ </child>
|
|
| 181 |
+ </object>
|
|
| 182 |
+ <packing>
|
|
| 183 |
+ <property name="name">file_selection</property>
|
|
| 184 |
+ </packing>
|
|
| 185 |
+ </child>
|
|
| 186 |
+ <child>
|
|
| 187 |
+ <object class="GtkBox" id="resource_box">
|
|
| 188 |
+ <property name="visible">True</property>
|
|
| 189 |
+ <property name="can-focus">False</property>
|
|
| 190 |
+ <property name="border-width">18</property>
|
|
| 191 |
+ <property name="orientation">vertical</property>
|
|
| 192 |
+ <property name="spacing">6</property>
|
|
| 193 |
+ <child>
|
|
| 194 |
+ <object class="GtkLabel">
|
|
| 195 |
+ <property name="visible">True</property>
|
|
| 196 |
+ <property name="can-focus">False</property>
|
|
| 197 |
+ <property name="label" translatable="yes">Choose Device</property>
|
|
| 198 |
+ <style>
|
|
| 199 |
+ <class name="large-header"/>
|
|
| 200 |
+ </style>
|
|
| 201 |
+ </object>
|
|
| 202 |
+ <packing>
|
|
| 203 |
+ <property name="expand">False</property>
|
|
| 204 |
+ <property name="fill">True</property>
|
|
| 205 |
+ <property name="position">0</property>
|
|
| 206 |
+ </packing>
|
|
| 207 |
+ </child>
|
|
| 208 |
+ <child>
|
|
| 209 |
+ <object class="GtkButton" id="resource_send">
|
|
| 210 |
+ <property name="label" translatable="yes">_Send Files</property>
|
|
| 211 |
+ <property name="visible">True</property>
|
|
| 212 |
+ <property name="sensitive">False</property>
|
|
| 213 |
+ <property name="can-focus">True</property>
|
|
| 214 |
+ <property name="receives-default">False</property>
|
|
| 215 |
+ <property name="halign">center</property>
|
|
| 216 |
+ <property name="use-underline">True</property>
|
|
| 217 |
+ <signal name="clicked" handler="_on_send_to_resource" swapped="no"/>
|
|
| 218 |
+ <style>
|
|
| 219 |
+ <class name="suggested-action"/>
|
|
| 220 |
+ </style>
|
|
| 221 |
+ </object>
|
|
| 222 |
+ <packing>
|
|
| 223 |
+ <property name="expand">False</property>
|
|
| 224 |
+ <property name="fill">True</property>
|
|
| 225 |
+ <property name="pack-type">end</property>
|
|
| 226 |
+ <property name="position">1</property>
|
|
| 227 |
+ </packing>
|
|
| 228 |
+ </child>
|
|
| 229 |
+ <child>
|
|
| 230 |
+ <object class="GtkLabel" id="resource_instructions">
|
|
| 231 |
+ <property name="visible">True</property>
|
|
| 232 |
+ <property name="can-focus">False</property>
|
|
| 233 |
+ <property name="justify">center</property>
|
|
| 234 |
+ <property name="wrap">True</property>
|
|
| 235 |
+ <property name="max-width-chars">50</property>
|
|
| 236 |
+ <style>
|
|
| 237 |
+ <class name="dim-label"/>
|
|
| 238 |
+ </style>
|
|
| 239 |
+ </object>
|
|
| 240 |
+ <packing>
|
|
| 241 |
+ <property name="expand">False</property>
|
|
| 242 |
+ <property name="fill">True</property>
|
|
| 243 |
+ <property name="position">2</property>
|
|
| 244 |
+ </packing>
|
|
| 245 |
+ </child>
|
|
| 246 |
+ <child>
|
|
| 247 |
+ <placeholder/>
|
|
| 248 |
+ </child>
|
|
| 249 |
+ </object>
|
|
| 250 |
+ <packing>
|
|
| 251 |
+ <property name="name">resource_selection</property>
|
|
| 252 |
+ <property name="position">1</property>
|
|
| 253 |
+ </packing>
|
|
| 254 |
+ </child>
|
|
| 255 |
+ </object>
|
|
| 256 |
+</interface>
|
| 1 |
-<?xml version="1.0" encoding="UTF-8"?>
|
|
| 2 |
-<!-- Generated with glade 3.36.0 -->
|
|
| 3 |
-<interface>
|
|
| 4 |
- <requires lib="gtk+" version="3.22"/>
|
|
| 5 |
- <object class="GtkGrid" id="send_file_grid">
|
|
| 6 |
- <property name="visible">True</property>
|
|
| 7 |
- <property name="can_focus">False</property>
|
|
| 8 |
- <property name="border_width">18</property>
|
|
| 9 |
- <property name="row_spacing">6</property>
|
|
| 10 |
- <property name="column_spacing">12</property>
|
|
| 11 |
- <child>
|
|
| 12 |
- <object class="GtkLabel">
|
|
| 13 |
- <property name="visible">True</property>
|
|
| 14 |
- <property name="can_focus">False</property>
|
|
| 15 |
- <property name="label" translatable="yes">Description</property>
|
|
| 16 |
- <property name="xalign">0</property>
|
|
| 17 |
- <style>
|
|
| 18 |
- <class name="dim-label"/>
|
|
| 19 |
- </style>
|
|
| 20 |
- </object>
|
|
| 21 |
- <packing>
|
|
| 22 |
- <property name="left_attach">0</property>
|
|
| 23 |
- <property name="top_attach">2</property>
|
|
| 24 |
- <property name="width">2</property>
|
|
| 25 |
- </packing>
|
|
| 26 |
- </child>
|
|
| 27 |
- <child>
|
|
| 28 |
- <object class="GtkScrolledWindow">
|
|
| 29 |
- <property name="height_request">70</property>
|
|
| 30 |
- <property name="visible">True</property>
|
|
| 31 |
- <property name="can_focus">True</property>
|
|
| 32 |
- <property name="hscrollbar_policy">never</property>
|
|
| 33 |
- <property name="shadow_type">in</property>
|
|
| 34 |
- <child>
|
|
| 35 |
- <object class="GtkTextView" id="description">
|
|
| 36 |
- <property name="visible">True</property>
|
|
| 37 |
- <property name="can_focus">True</property>
|
|
| 38 |
- <property name="wrap_mode">word-char</property>
|
|
| 39 |
- <property name="left_margin">6</property>
|
|
| 40 |
- <property name="right_margin">6</property>
|
|
| 41 |
- <property name="top_margin">6</property>
|
|
| 42 |
- <property name="bottom_margin">6</property>
|
|
| 43 |
- </object>
|
|
| 44 |
- </child>
|
|
| 45 |
- </object>
|
|
| 46 |
- <packing>
|
|
| 47 |
- <property name="left_attach">0</property>
|
|
| 48 |
- <property name="top_attach">3</property>
|
|
| 49 |
- <property name="width">2</property>
|
|
| 50 |
- </packing>
|
|
| 51 |
- </child>
|
|
| 52 |
- <child>
|
|
| 53 |
- <object class="GtkButton">
|
|
| 54 |
- <property name="label" translatable="yes">_Send Files</property>
|
|
| 55 |
- <property name="visible">True</property>
|
|
| 56 |
- <property name="can_focus">True</property>
|
|
| 57 |
- <property name="receives_default">True</property>
|
|
| 58 |
- <property name="tooltip_text" translatable="yes">Send</property>
|
|
| 59 |
- <property name="halign">center</property>
|
|
| 60 |
- <property name="use_underline">True</property>
|
|
| 61 |
- <signal name="clicked" handler="_send" swapped="no"/>
|
|
| 62 |
- <style>
|
|
| 63 |
- <class name="suggested-action"/>
|
|
| 64 |
- </style>
|
|
| 65 |
- </object>
|
|
| 66 |
- <packing>
|
|
| 67 |
- <property name="left_attach">0</property>
|
|
| 68 |
- <property name="top_attach">4</property>
|
|
| 69 |
- <property name="width">2</property>
|
|
| 70 |
- </packing>
|
|
| 71 |
- </child>
|
|
| 72 |
- <child>
|
|
| 73 |
- <object class="GtkLabel">
|
|
| 74 |
- <property name="visible">True</property>
|
|
| 75 |
- <property name="can_focus">False</property>
|
|
| 76 |
- <property name="label" translatable="yes">Files to send</property>
|
|
| 77 |
- <property name="xalign">0</property>
|
|
| 78 |
- <style>
|
|
| 79 |
- <class name="dim-label"/>
|
|
| 80 |
- </style>
|
|
| 81 |
- </object>
|
|
| 82 |
- <packing>
|
|
| 83 |
- <property name="left_attach">0</property>
|
|
| 84 |
- <property name="top_attach">0</property>
|
|
| 85 |
- <property name="width">2</property>
|
|
| 86 |
- </packing>
|
|
| 87 |
- </child>
|
|
| 88 |
- <child>
|
|
| 89 |
- <object class="GtkBox">
|
|
| 90 |
- <property name="visible">True</property>
|
|
| 91 |
- <property name="can_focus">False</property>
|
|
| 92 |
- <property name="hexpand">True</property>
|
|
| 93 |
- <property name="vexpand">True</property>
|
|
| 94 |
- <property name="orientation">vertical</property>
|
|
| 95 |
- <child>
|
|
| 96 |
- <object class="GtkScrolledWindow">
|
|
| 97 |
- <property name="visible">True</property>
|
|
| 98 |
- <property name="can_focus">True</property>
|
|
| 99 |
- <property name="hscrollbar_policy">never</property>
|
|
| 100 |
- <property name="shadow_type">in</property>
|
|
| 101 |
- <child>
|
|
| 102 |
- <object class="GtkViewport">
|
|
| 103 |
- <property name="visible">True</property>
|
|
| 104 |
- <property name="can_focus">False</property>
|
|
| 105 |
- <child>
|
|
| 106 |
- <object class="GtkListBox" id="listbox">
|
|
| 107 |
- <property name="visible">True</property>
|
|
| 108 |
- <property name="can_focus">False</property>
|
|
| 109 |
- <property name="vexpand">True</property>
|
|
| 110 |
- <property name="selection_mode">multiple</property>
|
|
| 111 |
- <property name="activate_on_single_click">False</property>
|
|
| 112 |
- </object>
|
|
| 113 |
- </child>
|
|
| 114 |
- </object>
|
|
| 115 |
- </child>
|
|
| 116 |
- </object>
|
|
| 117 |
- <packing>
|
|
| 118 |
- <property name="expand">False</property>
|
|
| 119 |
- <property name="fill">True</property>
|
|
| 120 |
- <property name="position">0</property>
|
|
| 121 |
- </packing>
|
|
| 122 |
- </child>
|
|
| 123 |
- <child>
|
|
| 124 |
- <object class="GtkToolbar">
|
|
| 125 |
- <property name="visible">True</property>
|
|
| 126 |
- <property name="can_focus">False</property>
|
|
| 127 |
- <property name="show_arrow">False</property>
|
|
| 128 |
- <property name="icon_size">1</property>
|
|
| 129 |
- <child>
|
|
| 130 |
- <object class="GtkToolButton">
|
|
| 131 |
- <property name="visible">True</property>
|
|
| 132 |
- <property name="can_focus">False</property>
|
|
| 133 |
- <property name="tooltip_text" translatable="yes">Add Files</property>
|
|
| 134 |
- <property name="use_underline">True</property>
|
|
| 135 |
- <property name="icon_name">list-add-symbolic</property>
|
|
| 136 |
- <signal name="clicked" handler="_select_files" swapped="no"/>
|
|
| 137 |
- </object>
|
|
| 138 |
- <packing>
|
|
| 139 |
- <property name="expand">False</property>
|
|
| 140 |
- <property name="homogeneous">False</property>
|
|
| 141 |
- </packing>
|
|
| 142 |
- </child>
|
|
| 143 |
- <child>
|
|
| 144 |
- <object class="GtkToolButton">
|
|
| 145 |
- <property name="visible">True</property>
|
|
| 146 |
- <property name="can_focus">False</property>
|
|
| 147 |
- <property name="tooltip_text" translatable="yes">Remove Files</property>
|
|
| 148 |
- <property name="use_underline">True</property>
|
|
| 149 |
- <property name="icon_name">list-remove-symbolic</property>
|
|
| 150 |
- <signal name="clicked" handler="_remove_files" swapped="no"/>
|
|
| 151 |
- </object>
|
|
| 152 |
- <packing>
|
|
| 153 |
- <property name="expand">False</property>
|
|
| 154 |
- <property name="homogeneous">True</property>
|
|
| 155 |
- </packing>
|
|
| 156 |
- </child>
|
|
| 157 |
- <style>
|
|
| 158 |
- <class name="inline-toolbar"/>
|
|
| 159 |
- </style>
|
|
| 160 |
- </object>
|
|
| 161 |
- <packing>
|
|
| 162 |
- <property name="expand">False</property>
|
|
| 163 |
- <property name="fill">True</property>
|
|
| 164 |
- <property name="position">1</property>
|
|
| 165 |
- </packing>
|
|
| 166 |
- </child>
|
|
| 167 |
- </object>
|
|
| 168 |
- <packing>
|
|
| 169 |
- <property name="left_attach">0</property>
|
|
| 170 |
- <property name="top_attach">1</property>
|
|
| 171 |
- <property name="width">2</property>
|
|
| 172 |
- </packing>
|
|
| 173 |
- </child>
|
|
| 174 |
- </object>
|
|
| 175 |
-</interface>
|
| ... | ... | @@ -426,6 +426,11 @@ .search-view-header label { |
| 426 | 426 |
color: @insensitive_fg_color;
|
| 427 | 427 |
}
|
| 428 | 428 |
|
| 429 |
+.resource-selector list row {
|
|
| 430 |
+ padding: 6px;
|
|
| 431 |
+ border-bottom: 1px solid @borders;
|
|
| 432 |
+}
|
|
| 433 |
+ |
|
| 429 | 434 |
/* Profile window */
|
| 430 | 435 |
#NicknameEntry:disabled {
|
| 431 | 436 |
font-size: 28px;
|
| ... | ... | @@ -184,6 +184,9 @@ def _on_jingle_request(self, event): |
| 184 | 184 |
content_types = []
|
| 185 | 185 |
for item in event.contents:
|
| 186 | 186 |
content_types.append(item.media)
|
| 187 |
+ if not any(item in ('audio', 'video') for item in content_types):
|
|
| 188 |
+ return
|
|
| 189 |
+ |
|
| 187 | 190 |
if 'audio' in content_types:
|
| 188 | 191 |
self._set_jingle_state(
|
| 189 | 192 |
'audio',
|
| ... | ... | @@ -245,7 +245,9 @@ def update_actions(self): |
| 245 | 245 |
|
| 246 | 246 |
# Send file (Jingle)
|
| 247 | 247 |
jingle_support = self.contact.supports(Namespace.JINGLE_FILE_TRANSFER_5)
|
| 248 |
- jingle_conditions = jingle_support and self.contact.is_available
|
|
| 248 |
+ jingle_conditions = bool(jingle_support and
|
|
| 249 |
+ self.contact.is_available and
|
|
| 250 |
+ not self.contact.is_pm_contact)
|
|
| 249 | 251 |
jingle = self._get_action('send-file-jingle-')
|
| 250 | 252 |
jingle.set_enabled(online and jingle_conditions)
|
| 251 | 253 |
|
| 1 |
+# Copyright (C) 2003-2014 Yann Leboulanger <asterix AT lagaule.org>
|
|
| 2 |
+# Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
|
|
| 3 |
+# Copyright (C) 2005-2007 Nikos Kouremenos <kourem AT gmail.com>
|
|
| 4 |
+# Copyright (C) 2006 Travis Shirk <travis AT pobox.com>
|
|
| 5 |
+#
|
|
| 6 |
+# This file is part of Gajim.
|
|
| 7 |
+#
|
|
| 8 |
+# Gajim is free software; you can redistribute it and/or modify
|
|
| 9 |
+# it under the terms of the GNU General Public License as published
|
|
| 10 |
+# by the Free Software Foundation; version 3 only.
|
|
| 11 |
+#
|
|
| 12 |
+# Gajim is distributed in the hope that it will be useful,
|
|
| 13 |
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
| 14 |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
| 15 |
+# GNU General Public License for more details.
|
|
| 16 |
+#
|
|
| 17 |
+# You should have received a copy of the GNU General Public License
|
|
| 18 |
+# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
|
| 19 |
+ |
|
| 20 |
+from pathlib import Path
|
|
| 21 |
+ |
|
| 22 |
+from gi.repository import Gdk
|
|
| 23 |
+from gi.repository import Gtk
|
|
| 24 |
+from gi.repository import Pango
|
|
| 25 |
+ |
|
| 26 |
+from nbxmpp import Namespace
|
|
| 27 |
+ |
|
| 28 |
+from gajim.common import app
|
|
| 29 |
+from gajim.common.i18n import _
|
|
| 30 |
+ |
|
| 31 |
+from .filechoosers import FileChooserDialog
|
|
| 32 |
+from .resource_selector import ResourceSelector
|
|
| 33 |
+from .util import get_builder
|
|
| 34 |
+ |
|
| 35 |
+ |
|
| 36 |
+class SendFileDialog(Gtk.ApplicationWindow):
|
|
| 37 |
+ def __init__(self, contact, send_callback, transient_for):
|
|
| 38 |
+ Gtk.ApplicationWindow.__init__(self)
|
|
| 39 |
+ self.set_application(app.app)
|
|
| 40 |
+ self.set_show_menubar(False)
|
|
| 41 |
+ self.set_resizable(True)
|
|
| 42 |
+ self.set_default_size(500, 350)
|
|
| 43 |
+ self.set_type_hint(Gdk.WindowTypeHint.DIALOG)
|
|
| 44 |
+ self.set_transient_for(transient_for)
|
|
| 45 |
+ self.set_title(_('Choose a File to Send…'))
|
|
| 46 |
+ self.set_destroy_with_parent(True)
|
|
| 47 |
+ |
|
| 48 |
+ self._contact = contact
|
|
| 49 |
+ self._send_callback = send_callback
|
|
| 50 |
+ |
|
| 51 |
+ self._ui = get_builder('file_transfer_send.ui')
|
|
| 52 |
+ self.add(self._ui.send_stack)
|
|
| 53 |
+ |
|
| 54 |
+ self._ui.resource_instructions.set_text(
|
|
| 55 |
+ _('%s is online with multiple devices.\n'
|
|
| 56 |
+ 'Choose the device you would like to send the '
|
|
| 57 |
+ 'file to.') % self._contact.name)
|
|
| 58 |
+ |
|
| 59 |
+ self._resource_selector = ResourceSelector(
|
|
| 60 |
+ contact,
|
|
| 61 |
+ constraints=[Namespace.JINGLE_FILE_TRANSFER_5])
|
|
| 62 |
+ self._resource_selector.connect(
|
|
| 63 |
+ 'selection-changed', self._on_resource_selection)
|
|
| 64 |
+ self._ui.resource_box.pack_start(self._resource_selector, 1, 0, 0)
|
|
| 65 |
+ |
|
| 66 |
+ self.connect('key-press-event', self._key_press_event)
|
|
| 67 |
+ self._ui.connect_signals(self)
|
|
| 68 |
+ self.show_all()
|
|
| 69 |
+ |
|
| 70 |
+ def _on_files_changed(self, _listbox, _row):
|
|
| 71 |
+ sensitive = bool(len(self._ui.listbox.get_children()) > 0)
|
|
| 72 |
+ self._ui.files_send.set_sensitive(sensitive)
|
|
| 73 |
+ |
|
| 74 |
+ def _on_resource_selection(self, _selector, state):
|
|
| 75 |
+ self._ui.resource_send.set_sensitive(state)
|
|
| 76 |
+ |
|
| 77 |
+ def _on_send_to_resource(self, _button):
|
|
| 78 |
+ resource_jid = self._resource_selector.get_jid()
|
|
| 79 |
+ self._send_files(resource_jid)
|
|
| 80 |
+ |
|
| 81 |
+ def _on_send_clicked(self, _button):
|
|
| 82 |
+ count = len(self._contact.get_resources())
|
|
| 83 |
+ if count == 0 or count > 1:
|
|
| 84 |
+ self._ui.send_stack.set_visible_child_name('resource_selection')
|
|
| 85 |
+ return
|
|
| 86 |
+ |
|
| 87 |
+ resource_jid = self._contact.get_resources()[0].jid
|
|
| 88 |
+ self._send_files(resource_jid)
|
|
| 89 |
+ |
|
| 90 |
+ def _send_files(self, resource_jid):
|
|
| 91 |
+ for file in self._ui.listbox.get_children():
|
|
| 92 |
+ self._send_callback(
|
|
| 93 |
+ resource_jid, str(file.path), self._get_description())
|
|
| 94 |
+ self.destroy()
|
|
| 95 |
+ |
|
| 96 |
+ def _select_files(self, _button):
|
|
| 97 |
+ FileChooserDialog(self._set_files,
|
|
| 98 |
+ select_multiple=True,
|
|
| 99 |
+ transient_for=self,
|
|
| 100 |
+ path=app.settings.get('last_send_dir'))
|
|
| 101 |
+ |
|
| 102 |
+ def _remove_files(self, _button):
|
|
| 103 |
+ selected = self._ui.listbox.get_selected_rows()
|
|
| 104 |
+ for item in selected:
|
|
| 105 |
+ self._ui.listbox.remove(item)
|
|
| 106 |
+ |
|
| 107 |
+ def _set_files(self, file_names):
|
|
| 108 |
+ for file in file_names:
|
|
| 109 |
+ row = FileRow(file)
|
|
| 110 |
+ if row.path.is_dir():
|
|
| 111 |
+ continue
|
|
| 112 |
+ last_dir = row.path.parent
|
|
| 113 |
+ self._ui.listbox.add(row)
|
|
| 114 |
+ self._ui.listbox.show_all()
|
|
| 115 |
+ app.settings.set('last_send_dir', str(last_dir))
|
|
| 116 |
+ |
|
| 117 |
+ def _get_description(self):
|
|
| 118 |
+ buffer_ = self._ui.description.get_buffer()
|
|
| 119 |
+ start, end = buffer_.get_bounds()
|
|
| 120 |
+ return buffer_.get_text(start, end, False)
|
|
| 121 |
+ |
|
| 122 |
+ def _key_press_event(self, _widget, event):
|
|
| 123 |
+ if event.keyval == Gdk.KEY_Escape:
|
|
| 124 |
+ self.destroy()
|
|
| 125 |
+ |
|
| 126 |
+ |
|
| 127 |
+class FileRow(Gtk.ListBoxRow):
|
|
| 128 |
+ def __init__(self, path):
|
|
| 129 |
+ Gtk.ListBoxRow.__init__(self)
|
|
| 130 |
+ self.path = Path(path)
|
|
| 131 |
+ label = Gtk.Label(label=self.path.name)
|
|
| 132 |
+ label.set_ellipsize(Pango.EllipsizeMode.END)
|
|
| 133 |
+ label.set_xalign(0)
|
|
| 134 |
+ self.add(label)
|
| ... | ... | @@ -21,7 +21,6 @@ |
| 21 | 21 |
import time
|
| 22 | 22 |
import logging
|
| 23 | 23 |
from functools import partial
|
| 24 |
-from pathlib import Path
|
|
| 25 | 24 |
from enum import IntEnum, unique
|
| 26 | 25 |
from datetime import datetime
|
| 27 | 26 |
|
| ... | ... | @@ -30,6 +29,8 @@ |
| 30 | 29 |
from gi.repository import GLib
|
| 31 | 30 |
from gi.repository import Pango
|
| 32 | 31 |
|
| 32 |
+from nbxmpp import JID
|
|
| 33 |
+ |
|
| 33 | 34 |
from gajim import gtkgui_helpers
|
| 34 | 35 |
|
| 35 | 36 |
from gajim.common import app
|
| ... | ... | @@ -47,7 +48,7 @@ |
| 47 | 48 |
from .dialogs import InformationDialog
|
| 48 | 49 |
from .dialogs import ErrorDialog
|
| 49 | 50 |
from .filechoosers import FileSaveDialog
|
| 50 |
-from .filechoosers import FileChooserDialog
|
|
| 51 |
+from .file_transfer_send import SendFileDialog
|
|
| 51 | 52 |
from .tooltips import FileTransfersTooltip
|
| 52 | 53 |
from .util import get_builder
|
| 53 | 54 |
|
| ... | ... | @@ -228,10 +229,11 @@ def on_open(widget, file_props): |
| 228 | 229 |
sectext = _('File name: %s') % GLib.markup_escape_text(file_name)
|
| 229 | 230 |
sectext += '\n' + _('Size: %s') % GLib.format_size_full(
|
| 230 | 231 |
file_props.size, self.units)
|
| 232 |
+ client = app.get_client(file_props.tt_account)
|
|
| 231 | 233 |
if file_props.type_ == 'r':
|
| 232 |
- jid = file_props.sender.split('/')[0]
|
|
| 233 |
- sender_name = app.contacts.get_first_contact_from_jid(
|
|
| 234 |
- file_props.tt_account, jid).get_shown_name()
|
|
| 234 |
+ jid = JID.from_string(file_props.sender)
|
|
| 235 |
+ sender_name = client.get_module('Contacts').get_contact(
|
|
| 236 |
+ jid.bare).name
|
|
| 235 | 237 |
sender = sender_name
|
| 236 | 238 |
else:
|
| 237 | 239 |
# You is a reply of who sent a file
|
| ... | ... | @@ -239,9 +241,9 @@ def on_open(widget, file_props): |
| 239 | 241 |
sectext += '\n' + _('Sender: %s') % sender
|
| 240 | 242 |
sectext += '\n' + _('Recipient: ')
|
| 241 | 243 |
if file_props.type_ == 's':
|
| 242 |
- jid = file_props.receiver.split('/')[0]
|
|
| 243 |
- receiver_name = app.contacts.get_first_contact_from_jid(
|
|
| 244 |
- file_props.tt_account, jid).get_shown_name()
|
|
| 244 |
+ jid = JID.from_string(file_props.receiver)
|
|
| 245 |
+ receiver_name = client.get_module('Contacts').get_contact(
|
|
| 246 |
+ jid.bare).name
|
|
| 245 | 247 |
recipient = receiver_name
|
| 246 | 248 |
else:
|
| 247 | 249 |
# You is a reply of who received a file
|
| ... | ... | @@ -250,7 +252,7 @@ def on_open(widget, file_props): |
| 250 | 252 |
if file_props.type_ == 'r':
|
| 251 | 253 |
sectext += '\n' + _('Saved in: %s') % file_path
|
| 252 | 254 |
|
| 253 |
- dialog = HigDialog(app.interface.roster.window,
|
|
| 255 |
+ dialog = HigDialog(app.window,
|
|
| 254 | 256 |
Gtk.MessageType.INFO,
|
| 255 | 257 |
Gtk.ButtonsType.NONE,
|
| 256 | 258 |
_('File transfer completed'),
|
| ... | ... | @@ -298,17 +300,10 @@ def show_stopped(self, jid, file_props, error_msg=''): |
| 298 | 300 |
self._ui.transfers_list.get_selection().unselect_all()
|
| 299 | 301 |
|
| 300 | 302 |
def show_hash_error(self, jid, file_props, account):
|
| 301 |
- |
|
| 302 |
- def on_yes(dummy, fjid, file_props, account):
|
|
| 303 |
+ def _on_yes():
|
|
| 303 | 304 |
# Delete old file
|
| 304 | 305 |
os.remove(file_props.file_name)
|
| 305 |
- jid, resource = app.get_room_and_nick_from_fjid(fjid)
|
|
| 306 |
- if resource:
|
|
| 307 |
- contact = app.contacts.get_contact(account, jid, resource)
|
|
| 308 |
- else:
|
|
| 309 |
- contact = app.contacts.get_contact_with_highest_priority(
|
|
| 310 |
- account, jid)
|
|
| 311 |
- fjid = contact.get_full_jid()
|
|
| 306 |
+ |
|
| 312 | 307 |
# Request the file to the sender
|
| 313 | 308 |
sid = helpers.get_random_string()
|
| 314 | 309 |
new_file_props = FilesProp.getNewFileProp(account, sid)
|
| ... | ... | @@ -319,12 +314,15 @@ def on_yes(dummy, fjid, file_props, account): |
| 319 | 314 |
new_file_props.date = file_props.date
|
| 320 | 315 |
new_file_props.hash_ = file_props.hash_
|
| 321 | 316 |
new_file_props.type_ = 'r'
|
| 322 |
- tsid = app.connections[account].get_module(
|
|
| 323 |
- 'Jingle').start_file_transfer(fjid, new_file_props, True)
|
|
| 317 |
+ tsid = client.get_module('Jingle').start_file_transfer(
|
|
| 318 |
+ jid, new_file_props, True)
|
|
| 324 | 319 |
|
| 325 | 320 |
new_file_props.transport_sid = tsid
|
| 326 | 321 |
self.add_transfer(account, contact, new_file_props)
|
| 327 | 322 |
|
| 323 |
+ client = app.get_client(account)
|
|
| 324 |
+ contact = client.get_module('Contacts').get_contact(jid)
|
|
| 325 |
+ |
|
| 328 | 326 |
if file_props.type_ == 'r':
|
| 329 | 327 |
file_name = os.path.basename(file_props.file_name)
|
| 330 | 328 |
else:
|
| ... | ... | @@ -339,16 +337,14 @@ def on_yes(dummy, fjid, file_props, account): |
| 339 | 337 |
text=_('_No')),
|
| 340 | 338 |
DialogButton.make('Accept',
|
| 341 | 339 |
text=_('_Download Again'),
|
| 342 |
- callback=on_yes,
|
|
| 343 |
- args=[jid,
|
|
| 344 |
- file_props,
|
|
| 345 |
- account])]).show()
|
|
| 340 |
+ callback=_on_yes)]).show()
|
|
| 346 | 341 |
|
| 347 | 342 |
def show_file_send_request(self, account, contact):
|
| 348 | 343 |
send_callback = partial(self.send_file, account, contact)
|
| 349 |
- SendFileDialog(send_callback, self.window)
|
|
| 344 |
+ SendFileDialog(contact, send_callback, self.window)
|
|
| 350 | 345 |
|
| 351 |
- def send_file(self, account, contact, file_path, file_desc=''):
|
|
| 346 |
+ def send_file(self, account, contact, resource_jid, file_path,
|
|
| 347 |
+ file_desc=''):
|
|
| 352 | 348 |
"""
|
| 353 | 349 |
Start the real transfer(upload) of the file
|
| 354 | 350 |
"""
|
| ... | ... | @@ -358,20 +354,15 @@ def send_file(self, account, contact, file_path, file_desc=''): |
| 358 | 354 |
ErrorDialog(pritext, sextext)
|
| 359 | 355 |
return
|
| 360 | 356 |
|
| 361 |
- if isinstance(contact, str):
|
|
| 362 |
- if contact.find('/') == -1:
|
|
| 363 |
- return
|
|
| 364 |
- (jid, resource) = contact.split('/', 1)
|
|
| 365 |
- contact = app.contacts.create_contact(jid=jid, account=account,
|
|
| 366 |
- resource=resource)
|
|
| 367 | 357 |
file_name = os.path.split(file_path)[1]
|
| 368 | 358 |
file_props = self.get_send_file_props(account, contact, file_path,
|
| 369 | 359 |
file_name, file_desc)
|
| 370 | 360 |
if file_props is None:
|
| 371 | 361 |
return False
|
| 372 | 362 |
|
| 373 |
- app.connections[account].get_module('Jingle').start_file_transfer(
|
|
| 374 |
- contact.get_full_jid(), file_props)
|
|
| 363 |
+ client = app.get_client(account)
|
|
| 364 |
+ client.get_module('Jingle').start_file_transfer(
|
|
| 365 |
+ str(resource_jid), file_props)
|
|
| 375 | 366 |
self.add_transfer(account, contact, file_props)
|
| 376 | 367 |
|
| 377 | 368 |
return True
|
| ... | ... | @@ -383,8 +374,8 @@ def _start_receive(self, file_path, account, contact, file_props): |
| 383 | 374 |
file_props.file_name = file_path
|
| 384 | 375 |
file_props.type_ = 'r'
|
| 385 | 376 |
self.add_transfer(account, contact, file_props)
|
| 386 |
- app.connections[account].get_module('Bytestream').send_file_approval(
|
|
| 387 |
- file_props)
|
|
| 377 |
+ client = app.get_client(account)
|
|
| 378 |
+ client.get_module('Bytestream').send_file_approval(file_props)
|
|
| 388 | 379 |
|
| 389 | 380 |
def on_file_request_accepted(self, account, contact, file_props):
|
| 390 | 381 |
def _on_accepted(account, contact, file_props, file_path):
|
| ... | ... | @@ -417,7 +408,7 @@ def _on_replace(): |
| 417 | 408 |
file_path, account, contact, file_props)
|
| 418 | 409 |
|
| 419 | 410 |
def _on_cancel():
|
| 420 |
- con.get_module('Bytestream').send_file_rejection(
|
|
| 411 |
+ client.get_module('Bytestream').send_file_rejection(
|
|
| 421 | 412 |
file_props)
|
| 422 | 413 |
|
| 423 | 414 |
ConfirmationDialog(
|
| ... | ... | @@ -447,10 +438,10 @@ def _on_cancel(): |
| 447 | 438 |
self._start_receive(file_path, account, contact, file_props)
|
| 448 | 439 |
|
| 449 | 440 |
# Show file save as dialog
|
| 450 |
- con = app.connections[account]
|
|
| 441 |
+ client = app.get_client(account)
|
|
| 451 | 442 |
accept_cb = partial(_on_accepted, account, contact, file_props)
|
| 452 |
- cancel_cb = partial(con.get_module('Bytestream').send_file_rejection,
|
|
| 453 |
- file_props)
|
|
| 443 |
+ cancel_cb = partial(
|
|
| 444 |
+ client.get_module('Bytestream').send_file_rejection, file_props)
|
|
| 454 | 445 |
FileSaveDialog(accept_cb,
|
| 455 | 446 |
cancel_cb,
|
| 456 | 447 |
path=app.settings.get('last_save_dir'),
|
| ... | ... | @@ -478,12 +469,12 @@ def _on_ok(): |
| 478 | 469 |
self.on_file_request_accepted(account, contact, file_props)
|
| 479 | 470 |
|
| 480 | 471 |
def _on_cancel():
|
| 481 |
- app.connections[account].get_module(
|
|
| 472 |
+ app.get_client(account).get_module(
|
|
| 482 | 473 |
'Bytestream').send_file_rejection(file_props)
|
| 483 | 474 |
|
| 484 | 475 |
ConfirmationDialog(
|
| 485 | 476 |
_('File Transfer Request'),
|
| 486 |
- _('%s wants to send you a file') % contact.get_shown_name(),
|
|
| 477 |
+ _('%s wants to send you a file') % contact.name,
|
|
| 487 | 478 |
sectext,
|
| 488 | 479 |
[DialogButton.make('Cancel',
|
| 489 | 480 |
callback=_on_cancel),
|
| ... | ... | @@ -518,13 +509,13 @@ def set_status(self, file_props, status): |
| 518 | 509 |
text += received_size + '/' + full_size
|
| 519 | 510 |
self.model.set(iter_, Column.PROGRESS, text)
|
| 520 | 511 |
|
| 521 |
- def pulse():
|
|
| 522 |
- p = self.model.get(iter_, Column.PULSE)[0]
|
|
| 523 |
- if p == GLib.MAXINT32:
|
|
| 512 |
+ def _pulse():
|
|
| 513 |
+ pulse_value = self.model.get(iter_, Column.PULSE)[0]
|
|
| 514 |
+ if pulse_value == GLib.MAXINT32:
|
|
| 524 | 515 |
return False
|
| 525 |
- self.model.set(iter_, Column.PULSE, p + 1)
|
|
| 516 |
+ self.model.set(iter_, Column.PULSE, pulse_value + 1)
|
|
| 526 | 517 |
return True
|
| 527 |
- GLib.timeout_add(100, pulse)
|
|
| 518 |
+ GLib.timeout_add(100, _pulse)
|
|
| 528 | 519 |
elif status == 'hash_error':
|
| 529 | 520 |
text = _('File error') + '\n'
|
| 530 | 521 |
received_size = GLib.format_size_full(
|
| ... | ... | @@ -569,6 +560,9 @@ def _get_eta_and_speed(self, full_size, transfered_size, file_props): |
| 569 | 560 |
if not file_props.transfered_size:
|
| 570 | 561 |
return 0., 0.
|
| 571 | 562 |
|
| 563 |
+ if file_props.elapsed_time == 0:
|
|
| 564 |
+ return 0., 0.
|
|
| 565 |
+ |
|
| 572 | 566 |
if len(file_props.transfered_size) == 1:
|
| 573 | 567 |
speed = round(float(transfered_size) / file_props.elapsed_time)
|
| 574 | 568 |
else:
|
| ... | ... | @@ -595,7 +589,7 @@ def _remove_transfer(self, iter_, sid, file_props): |
| 595 | 589 |
account = file_props.tt_account
|
| 596 | 590 |
if account in app.connections:
|
| 597 | 591 |
# there is a connection to the account
|
| 598 |
- app.connections[account].get_module(
|
|
| 592 |
+ app.get_client(account).get_module(
|
|
| 599 | 593 |
'Bytestream').remove_transfer(file_props)
|
| 600 | 594 |
if file_props.type_ == 'r': # we receive a file
|
| 601 | 595 |
other = file_props.sender
|
| ... | ... | @@ -611,8 +605,7 @@ def _remove_transfer(self, iter_, sid, file_props): |
| 611 | 605 |
for event in app.events.get_events(account, jid, [ev_type]):
|
| 612 | 606 |
if event.file_props.sid == file_props.sid:
|
| 613 | 607 |
app.events.remove_events(account, jid, event)
|
| 614 |
- app.interface.roster.draw_contact(jid, account)
|
|
| 615 |
- app.interface.roster.show_title()
|
|
| 608 |
+ |
|
| 616 | 609 |
FilesProp.deleteFileProp(file_props)
|
| 617 | 610 |
del file_props
|
| 618 | 611 |
|
| ... | ... | @@ -678,8 +671,9 @@ def set_progress(self, typ, sid, transfered_size, iter_=None): |
| 678 | 671 |
self.model.set(iter_, 0, self.icons[status])
|
| 679 | 672 |
if transfered_size == full_size:
|
| 680 | 673 |
# If we are receiver and this is a jingle session
|
| 681 |
- if file_props.type_ == 'r' and \
|
|
| 682 |
- file_props.session_type == 'jingle' and file_props.hash_:
|
|
| 674 |
+ if (file_props.type_ == 'r' and
|
|
| 675 |
+ file_props.session_type == 'jingle' and
|
|
| 676 |
+ file_props.hash_):
|
|
| 683 | 677 |
# Show that we are computing the hash
|
| 684 | 678 |
self.set_status(file_props, 'computing')
|
| 685 | 679 |
else:
|
| ... | ... | @@ -753,7 +747,7 @@ def add_transfer(self, account, contact, file_props): |
| 753 | 747 |
else:
|
| 754 | 748 |
file_name = file_props.name
|
| 755 | 749 |
text_props = GLib.markup_escape_text(file_name) + '\n'
|
| 756 |
- text_props += contact.get_shown_name()
|
|
| 750 |
+ text_props += contact.name
|
|
| 757 | 751 |
self.model.set(iter_,
|
| 758 | 752 |
1,
|
| 759 | 753 |
text_labels,
|
| ... | ... | @@ -916,11 +910,11 @@ def _on_cancel_button_clicked(self, widget): |
| 916 | 910 |
account = file_props.tt_account
|
| 917 | 911 |
if account not in app.connections:
|
| 918 | 912 |
return
|
| 919 |
- con = app.connections[account]
|
|
| 913 |
+ client = app.get_client(account)
|
|
| 920 | 914 |
# Check if we are in a IBB transfer
|
| 921 | 915 |
if file_props.direction:
|
| 922 |
- con.get_module('IBB').send_close(file_props)
|
|
| 923 |
- con.get_module('Bytestream').disconnect_transfer(file_props)
|
|
| 916 |
+ client.get_module('IBB').send_close(file_props)
|
|
| 917 |
+ client.get_module('Bytestream').disconnect_transfer(file_props)
|
|
| 924 | 918 |
self.set_status(file_props, 'stop')
|
| 925 | 919 |
|
| 926 | 920 |
def _on_notify_ft_complete_toggled(self, widget, *args):
|
| ... | ... | @@ -1028,70 +1022,3 @@ def _on_remove_menuitem_activate(self, widget): |
| 1028 | 1022 |
def _on_file_transfers_window_key_press_event(self, widget, event):
|
| 1029 | 1023 |
if event.keyval == Gdk.KEY_Escape: # ESCAPE
|
| 1030 | 1024 |
self.window.hide()
|
| 1031 |
- |
|
| 1032 |
- |
|
| 1033 |
-class SendFileDialog(Gtk.ApplicationWindow):
|
|
| 1034 |
- def __init__(self, send_callback, transient_for):
|
|
| 1035 |
- Gtk.ApplicationWindow.__init__(self)
|
|
| 1036 |
- self.set_name('SendFileDialog')
|
|
| 1037 |
- self.set_application(app.app)
|
|
| 1038 |
- self.set_show_menubar(False)
|
|
| 1039 |
- self.set_resizable(True)
|
|
| 1040 |
- self.set_default_size(500, 350)
|
|
| 1041 |
- self.set_type_hint(Gdk.WindowTypeHint.DIALOG)
|
|
| 1042 |
- self.set_transient_for(transient_for)
|
|
| 1043 |
- self.set_title(_('Choose a File to Send…'))
|
|
| 1044 |
- self.set_destroy_with_parent(True)
|
|
| 1045 |
- |
|
| 1046 |
- self._send_callback = send_callback
|
|
| 1047 |
- |
|
| 1048 |
- self._ui = get_builder('filetransfers_send_file_dialog.ui')
|
|
| 1049 |
- self.add(self._ui.send_file_grid)
|
|
| 1050 |
- self.connect('key-press-event', self._key_press_event)
|
|
| 1051 |
- self._ui.connect_signals(self)
|
|
| 1052 |
- self.show_all()
|
|
| 1053 |
- |
|
| 1054 |
- def _send(self, button):
|
|
| 1055 |
- for file in self._ui.listbox.get_children():
|
|
| 1056 |
- self._send_callback(str(file.path), self._get_description())
|
|
| 1057 |
- self.destroy()
|
|
| 1058 |
- |
|
| 1059 |
- def _select_files(self, button):
|
|
| 1060 |
- FileChooserDialog(self._set_files,
|
|
| 1061 |
- select_multiple=True,
|
|
| 1062 |
- transient_for=self,
|
|
| 1063 |
- path=app.settings.get('last_send_dir'))
|
|
| 1064 |
- |
|
| 1065 |
- def _remove_files(self, button):
|
|
| 1066 |
- selected = self._ui.listbox.get_selected_rows()
|
|
| 1067 |
- for item in selected:
|
|
| 1068 |
- self._ui.listbox.remove(item)
|
|
| 1069 |
- |
|
| 1070 |
- def _set_files(self, filenames):
|
|
| 1071 |
- for file in filenames:
|
|
| 1072 |
- row = FileRow(file)
|
|
| 1073 |
- if row.path.is_dir():
|
|
| 1074 |
- continue
|
|
| 1075 |
- last_dir = row.path.parent
|
|
| 1076 |
- self._ui.listbox.add(row)
|
|
| 1077 |
- self._ui.listbox.show_all()
|
|
| 1078 |
- app.settings.set('last_send_dir', str(last_dir))
|
|
| 1079 |
- |
|
| 1080 |
- def _get_description(self):
|
|
| 1081 |
- buffer_ = self._ui.description.get_buffer()
|
|
| 1082 |
- start, end = buffer_.get_bounds()
|
|
| 1083 |
- return buffer_.get_text(start, end, False)
|
|
| 1084 |
- |
|
| 1085 |
- def _key_press_event(self, widget, event):
|
|
| 1086 |
- if event.keyval == Gdk.KEY_Escape:
|
|
| 1087 |
- self.destroy()
|
|
| 1088 |
- |
|
| 1089 |
- |
|
| 1090 |
-class FileRow(Gtk.ListBoxRow):
|
|
| 1091 |
- def __init__(self, path):
|
|
| 1092 |
- Gtk.ListBoxRow.__init__(self)
|
|
| 1093 |
- self.path = Path(path)
|
|
| 1094 |
- label = Gtk.Label(label=self.path.name)
|
|
| 1095 |
- label.set_ellipsize(Pango.EllipsizeMode.END)
|
|
| 1096 |
- label.set_xalign(0)
|
|
| 1097 |
- self.add(label)
|
| 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 |
+import locale
|
|
| 16 |
+import logging
|
|
| 17 |
+ |
|
| 18 |
+from gi.repository import GObject
|
|
| 19 |
+from gi.repository import Gtk
|
|
| 20 |
+ |
|
| 21 |
+from gajim.common import app
|
|
| 22 |
+from gajim.common.i18n import _
|
|
| 23 |
+ |
|
| 24 |
+log = logging.getLogger('gajim.gui.resource_selector')
|
|
| 25 |
+ |
|
| 26 |
+ |
|
| 27 |
+class ResourceSelector(Gtk.ScrolledWindow):
|
|
| 28 |
+ |
|
| 29 |
+ __gsignals__ = {
|
|
| 30 |
+ 'selection-changed': (
|
|
| 31 |
+ GObject.SignalFlags.RUN_LAST,
|
|
| 32 |
+ None,
|
|
| 33 |
+ (bool, )),
|
|
| 34 |
+ }
|
|
| 35 |
+ |
|
| 36 |
+ def __init__(self, contact, constraints=None):
|
|
| 37 |
+ Gtk.ScrolledWindow.__init__(self)
|
|
| 38 |
+ self.set_shadow_type(Gtk.ShadowType.IN)
|
|
| 39 |
+ self.set_size_request(-1, 200)
|
|
| 40 |
+ self.get_style_context().add_class('resource-selector')
|
|
| 41 |
+ |
|
| 42 |
+ self._listbox = Gtk.ListBox()
|
|
| 43 |
+ self._listbox.set_sort_func(self._sort_func)
|
|
| 44 |
+ self._listbox.connect('row-selected', self._on_row_selected)
|
|
| 45 |
+ self.add(self._listbox)
|
|
| 46 |
+ |
|
| 47 |
+ self._contact = contact
|
|
| 48 |
+ self._contact.connect('presence-update', self._on_update)
|
|
| 49 |
+ self._contact.connect('caps-update', self._on_update)
|
|
| 50 |
+ |
|
| 51 |
+ # Constraints include Namespaces a resource has to support
|
|
| 52 |
+ self._constraints = constraints or []
|
|
| 53 |
+ |
|
| 54 |
+ self._set_placeholder()
|
|
| 55 |
+ self._add_entries()
|
|
| 56 |
+ |
|
| 57 |
+ self.show_all()
|
|
| 58 |
+ |
|
| 59 |
+ @staticmethod
|
|
| 60 |
+ def _sort_func(row1, row2):
|
|
| 61 |
+ return locale.strcoll(
|
|
| 62 |
+ row1.device_text.lower(), row2.device_text.lower())
|
|
| 63 |
+ |
|
| 64 |
+ def _on_row_selected(self, _listbox, row):
|
|
| 65 |
+ state = bool(row is not None)
|
|
| 66 |
+ self.emit('selection-changed', state)
|
|
| 67 |
+ |
|
| 68 |
+ def _set_placeholder(self):
|
|
| 69 |
+ image = Gtk.Image.new_from_icon_name(
|
|
| 70 |
+ 'dialog-warning-symbolic', Gtk.IconSize.DND)
|
|
| 71 |
+ label = Gtk.Label(label=_('No devices online'))
|
|
| 72 |
+ box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
|
|
| 73 |
+ box.set_valign(Gtk.Align.CENTER)
|
|
| 74 |
+ box.get_style_context().add_class('dim-label')
|
|
| 75 |
+ box.add(image)
|
|
| 76 |
+ box.add(label)
|
|
| 77 |
+ box.show_all()
|
|
| 78 |
+ self._listbox.set_placeholder(box)
|
|
| 79 |
+ |
|
| 80 |
+ def _add_entries(self):
|
|
| 81 |
+ for resource in self._contact.iter_resources():
|
|
| 82 |
+ self._listbox.add(ResourceRow(resource, self._constraints))
|
|
| 83 |
+ |
|
| 84 |
+ def _on_update(self, _contact, _signal_name):
|
|
| 85 |
+ for child in self._listbox.get_children():
|
|
| 86 |
+ self._listbox.remove(child)
|
|
| 87 |
+ self._add_entries()
|
|
| 88 |
+ |
|
| 89 |
+ def get_jid(self):
|
|
| 90 |
+ return self._listbox.get_selected_row().jid
|
|
| 91 |
+ |
|
| 92 |
+ |
|
| 93 |
+class ResourceRow(Gtk.ListBoxRow):
|
|
| 94 |
+ def __init__(self, resource_contact, constraints):
|
|
| 95 |
+ Gtk.ListBoxRow.__init__(self)
|
|
| 96 |
+ |
|
| 97 |
+ self.jid = resource_contact.jid
|
|
| 98 |
+ |
|
| 99 |
+ icon_name = 'computer-symbolic'
|
|
| 100 |
+ tooltip_text = _('Computer')
|
|
| 101 |
+ self.device_text = resource_contact.jid.resource
|
|
| 102 |
+ |
|
| 103 |
+ disco_info = app.storage.cache.get_last_disco_info(
|
|
| 104 |
+ resource_contact.jid)
|
|
| 105 |
+ if disco_info is not None:
|
|
| 106 |
+ name, type_ = self._get_client_identity(disco_info)
|
|
| 107 |
+ if name is not None:
|
|
| 108 |
+ self.device_text = f'{name} ({resource_contact.jid.resource})'
|
|
| 109 |
+ if type_ is not None:
|
|
| 110 |
+ if type_ == 'phone':
|
|
| 111 |
+ icon_name = 'phone-symbolic'
|
|
| 112 |
+ tooltip_text = _('Phone')
|
|
| 113 |
+ |
|
| 114 |
+ image = Gtk.Image()
|
|
| 115 |
+ image.set_from_icon_name(icon_name, Gtk.IconSize.DND)
|
|
| 116 |
+ image.set_tooltip_text(tooltip_text)
|
|
| 117 |
+ |
|
| 118 |
+ name_label = Gtk.Label()
|
|
| 119 |
+ name_label.set_text(self.device_text)
|
|
| 120 |
+ |
|
| 121 |
+ box = Gtk.Box(spacing=12)
|
|
| 122 |
+ box.add(image)
|
|
| 123 |
+ box.add(name_label)
|
|
| 124 |
+ |
|
| 125 |
+ for constraint in constraints:
|
|
| 126 |
+ if not resource_contact.supports(constraint):
|
|
| 127 |
+ self.set_sensitive(False)
|
|
| 128 |
+ self.set_tooltip_text(_('This devices is not compatible.'))
|
|
| 129 |
+ |
|
| 130 |
+ self.add(box)
|
|
| 131 |
+ self.show_all()
|
|
| 132 |
+ |
|
| 133 |
+ @staticmethod
|
|
| 134 |
+ def _get_client_identity(disco_info):
|
|
| 135 |
+ for identity in disco_info.identities:
|
|
| 136 |
+ if identity.category == 'client':
|
|
| 137 |
+ return identity.name, identity.type
|
|
| 138 |
+ return None, None
|
| ... | ... | @@ -33,6 +33,8 @@ |
| 33 | 33 |
from gi.repository import GLib
|
| 34 | 34 |
from gi.repository import Pango
|
| 35 | 35 |
|
| 36 |
+from nbxmpp import JID
|
|
| 37 |
+ |
|
| 36 | 38 |
from gajim.common import app
|
| 37 | 39 |
from gajim.common import helpers
|
| 38 | 40 |
from gajim.common.const import AvatarSize
|
| ... | ... | @@ -304,20 +306,19 @@ def _create_tooltip(self, file_props, _sid): |
| 304 | 306 |
file_name = file_props.name
|
| 305 | 307 |
properties.append((_('File Name: '),
|
| 306 | 308 |
GLib.markup_escape_text(file_name)))
|
| 309 |
+ |
|
| 310 |
+ client = app.get_client(file_props.tt_account)
|
|
| 307 | 311 |
if file_props.type_ == 'r':
|
| 308 | 312 |
type_ = Q_('?Noun:Download')
|
| 309 | 313 |
actor = _('Sender: ')
|
| 310 |
- sender = file_props.sender.split('/')[0]
|
|
| 311 |
- name = app.contacts.get_first_contact_from_jid(
|
|
| 312 |
- file_props.tt_account, sender).get_shown_name()
|
|
| 314 |
+ sender = JID.from_string(file_props.sender)
|
|
| 315 |
+ name = client.get_module('Contacts').get_contact(sender.bare).name
|
|
| 313 | 316 |
else:
|
| 314 | 317 |
type_ = Q_('?Noun:Upload')
|
| 315 | 318 |
actor = _('Recipient: ')
|
| 316 |
- receiver = file_props.receiver
|
|
| 317 |
- if hasattr(receiver, 'name'):
|
|
| 318 |
- name = receiver.get_shown_name()
|
|
| 319 |
- else:
|
|
| 320 |
- name = receiver.split('/')[0]
|
|
| 319 |
+ receiver = JID.from_string(file_props.receiver)
|
|
| 320 |
+ name = client.get_module('Contacts').get_contact(
|
|
| 321 |
+ receiver.bare).name
|
|
| 321 | 322 |
properties.append((Q_('?transfer type:Type: '), type_))
|
| 322 | 323 |
properties.append((actor, GLib.markup_escape_text(name)))
|
| 323 | 324 |
|
| ... | ... | @@ -757,14 +757,10 @@ def handle_event_file_request_error(self, event): |
| 757 | 757 |
text=event.file_props.name)
|
| 758 | 758 |
|
| 759 | 759 |
def handle_event_file_request(self, event):
|
| 760 |
- # TODO
|
|
| 761 | 760 |
account = event.conn.name
|
| 762 |
- if event.jid not in app.contacts.get_jid_list(account):
|
|
| 763 |
- contact = app.contacts.create_not_in_roster_contact(
|
|
| 764 |
- jid=event.jid, account=account)
|
|
| 765 |
- app.contacts.add_contact(account, contact)
|
|
| 766 |
- self.roster.add_contact(event.jid, account)
|
|
| 767 |
- contact = app.contacts.get_first_contact_from_jid(account, event.jid)
|
|
| 761 |
+ client = app.get_client(account)
|
|
| 762 |
+ contact = client.get_module('Contacts').get_contact(event.jid)
|
|
| 763 |
+ |
|
| 768 | 764 |
if event.file_props.session_type == 'jingle':
|
| 769 | 765 |
request = \
|
| 770 | 766 |
event.stanza.getTag('jingle').getTag('content').getTag(
|
| ... | ... | @@ -781,8 +777,7 @@ def handle_event_file_request(self, event): |
| 781 | 777 |
file_event = events.FileRequestEvent(event.file_props)
|
| 782 | 778 |
self.add_event(account, event.jid, file_event)
|
| 783 | 779 |
if helpers.allow_showing_notification(account):
|
| 784 |
- txt = _('%s wants to send you a file.') % app.get_name_from_jid(
|
|
| 785 |
- account, event.jid)
|
|
| 780 |
+ txt = _('%s wants to send you a file.') % contact.name
|
|
| 786 | 781 |
event_type = _('File Transfer Request')
|
| 787 | 782 |
app.notification.popup(
|
| 788 | 783 |
event_type,
|
| ... | ... | @@ -823,11 +818,11 @@ def handle_event_file_rcv_completed(self, account, file_props): |
| 823 | 818 |
if file_props.error == 0:
|
| 824 | 819 |
file_transfers.set_progress(
|
| 825 | 820 |
file_props.type_, file_props.sid, file_props.received_len)
|
| 826 |
- jid = app.get_jid_without_resource(str(file_props.receiver))
|
|
| 821 |
+ jid = JID.from_string(file_props.receiver)
|
|
| 827 | 822 |
app.nec.push_incoming_event(
|
| 828 | 823 |
NetworkEvent('file-transfer-completed',
|
| 829 | 824 |
file_props=file_props,
|
| 830 |
- jid=jid))
|
|
| 825 |
+ jid=jid.bare))
|
|
| 831 | 826 |
|
| 832 | 827 |
else:
|
| 833 | 828 |
file_transfers.set_status(file_props, 'stop')
|
| ... | ... | @@ -947,56 +942,55 @@ def _popup_ft_result(self, account, jid, file_props): |
| 947 | 942 |
self.add_event(account, jid, event)
|
| 948 | 943 |
|
| 949 | 944 |
if file_props is not None:
|
| 945 |
+ client = app.get_client(account)
|
|
| 946 |
+ |
|
| 950 | 947 |
if file_props.type_ == 'r':
|
| 951 |
- # Get the name of the sender, as it is in the roster
|
|
| 952 |
- sender = file_props.sender.split('/')[0]
|
|
| 953 |
- name = app.contacts.get_first_contact_from_jid(
|
|
| 954 |
- account, sender).get_shown_name()
|
|
| 948 |
+ jid = JID.from_string(file_props.sender)
|
|
| 949 |
+ contact = client.get_module('contacts').get_contact(jid.bare)
|
|
| 955 | 950 |
filename = os.path.basename(file_props.file_name)
|
| 956 | 951 |
|
| 957 | 952 |
if event_type == _('File Transfer Completed'):
|
| 958 | 953 |
txt = _('%(filename)s received from %(name)s.') % {
|
| 959 | 954 |
'filename': filename,
|
| 960 |
- 'name': name}
|
|
| 955 |
+ 'name': contact.name}
|
|
| 961 | 956 |
icon_name = 'emblem-default'
|
| 962 | 957 |
elif event_type == _('File Transfer Stopped'):
|
| 963 | 958 |
txt = _('File transfer of %(filename)s from %(name)s '
|
| 964 | 959 |
'stopped.') % {
|
| 965 | 960 |
'filename': filename,
|
| 966 |
- 'name': name}
|
|
| 961 |
+ 'name': contact.name}
|
|
| 967 | 962 |
icon_name = 'process-stop'
|
| 968 | 963 |
else: # File transfer hash error
|
| 969 | 964 |
txt = _('File transfer of %(filename)s from %(name)s '
|
| 970 | 965 |
'failed.') % {
|
| 971 | 966 |
'filename': filename,
|
| 972 |
- 'name': name}
|
|
| 967 |
+ 'name': contact.name}
|
|
| 973 | 968 |
icon_name = 'process-stop'
|
| 974 | 969 |
else:
|
| 975 | 970 |
receiver = file_props.receiver
|
| 976 | 971 |
if hasattr(receiver, 'jid'):
|
| 977 | 972 |
receiver = receiver.jid
|
| 978 |
- receiver = receiver.split('/')[0]
|
|
| 979 |
- # Get the name of the contact, as it is in the roster
|
|
| 980 |
- name = app.contacts.get_first_contact_from_jid(
|
|
| 981 |
- account, receiver).get_shown_name()
|
|
| 973 |
+ |
|
| 974 |
+ jid = JID.from_string(receiver)
|
|
| 975 |
+ contact = client.get_module('contacts').get_contact(jid.bare)
|
|
| 982 | 976 |
filename = os.path.basename(file_props.file_name)
|
| 983 | 977 |
if event_type == _('File Transfer Completed'):
|
| 984 | 978 |
txt = _('You successfully sent %(filename)s to '
|
| 985 | 979 |
'%(name)s.') % {
|
| 986 | 980 |
'filename': filename,
|
| 987 |
- 'name': name}
|
|
| 981 |
+ 'name': contact.name}
|
|
| 988 | 982 |
icon_name = 'emblem-default'
|
| 989 | 983 |
elif event_type == _('File Transfer Stopped'):
|
| 990 | 984 |
txt = _('File transfer of %(filename)s to %(name)s '
|
| 991 | 985 |
'stopped.') % {
|
| 992 | 986 |
'filename': filename,
|
| 993 |
- 'name': name}
|
|
| 987 |
+ 'name': contact.name}
|
|
| 994 | 988 |
icon_name = 'process-stop'
|
| 995 | 989 |
else: # File transfer hash error
|
| 996 | 990 |
txt = _('File transfer of %(filename)s to %(name)s '
|
| 997 | 991 |
'failed.') % {
|
| 998 | 992 |
'filename': filename,
|
| 999 |
- 'name': name}
|
|
| 993 |
+ 'name': contact.name}
|
|
| 1000 | 994 |
icon_name = 'process-stop'
|
| 1001 | 995 |
else:
|
| 1002 | 996 |
txt = ''
|