handle GUI while checking file hash. Show show re-request dialog when hash is incorrect. TODO: re-request file to sender.
This commit is contained in:
parent
ca1eadaa2d
commit
df17f8751d
|
@ -1615,16 +1615,15 @@ class YesNoDialog(HigDialog):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, pritext, sectext='', checktext='', on_response_yes=None,
|
def __init__(self, pritext, sectext='', checktext='', on_response_yes=None,
|
||||||
on_response_no=None):
|
on_response_no=None, type_=gtk.MESSAGE_QUESTION):
|
||||||
self.user_response_yes = on_response_yes
|
self.user_response_yes = on_response_yes
|
||||||
self.user_response_no = on_response_no
|
self.user_response_no = on_response_no
|
||||||
if hasattr(gajim.interface, 'roster') and gajim.interface.roster:
|
if hasattr(gajim.interface, 'roster') and gajim.interface.roster:
|
||||||
parent = gajim.interface.roster.window
|
parent = gajim.interface.roster.window
|
||||||
else:
|
else:
|
||||||
parent = None
|
parent = None
|
||||||
HigDialog.__init__(self, parent, gtk.MESSAGE_QUESTION,
|
HigDialog.__init__(self, parent, type_, gtk.BUTTONS_YES_NO, pritext,
|
||||||
gtk.BUTTONS_YES_NO, pritext, sectext,
|
sectext, on_response_yes=self.on_response_yes,
|
||||||
on_response_yes=self.on_response_yes,
|
|
||||||
on_response_no=self.on_response_no)
|
on_response_no=self.on_response_no)
|
||||||
|
|
||||||
if checktext:
|
if checktext:
|
||||||
|
|
|
@ -46,7 +46,8 @@ C_FILE = 2
|
||||||
C_TIME = 3
|
C_TIME = 3
|
||||||
C_PROGRESS = 4
|
C_PROGRESS = 4
|
||||||
C_PERCENT = 5
|
C_PERCENT = 5
|
||||||
C_SID = 6
|
C_PULSE = 6
|
||||||
|
C_SID = 7
|
||||||
|
|
||||||
|
|
||||||
class FileTransfersWindow:
|
class FileTransfersWindow:
|
||||||
|
@ -65,7 +66,8 @@ class FileTransfersWindow:
|
||||||
shall_notify = gajim.config.get('notify_on_file_complete')
|
shall_notify = gajim.config.get('notify_on_file_complete')
|
||||||
self.notify_ft_checkbox.set_active(shall_notify
|
self.notify_ft_checkbox.set_active(shall_notify
|
||||||
)
|
)
|
||||||
self.model = gtk.ListStore(gtk.gdk.Pixbuf, str, str, str, str, int, str)
|
self.model = gtk.ListStore(gtk.gdk.Pixbuf, str, str, str, str, int,
|
||||||
|
int, str)
|
||||||
self.tree.set_model(self.model)
|
self.tree.set_model(self.model)
|
||||||
col = gtk.TreeViewColumn()
|
col = gtk.TreeViewColumn()
|
||||||
|
|
||||||
|
@ -112,6 +114,7 @@ class FileTransfersWindow:
|
||||||
col.pack_start(renderer, expand=False)
|
col.pack_start(renderer, expand=False)
|
||||||
col.add_attribute(renderer, 'text', C_PROGRESS)
|
col.add_attribute(renderer, 'text', C_PROGRESS)
|
||||||
col.add_attribute(renderer, 'value', C_PERCENT)
|
col.add_attribute(renderer, 'value', C_PERCENT)
|
||||||
|
col.add_attribute(renderer, 'pulse', C_PULSE)
|
||||||
col.set_resizable(True)
|
col.set_resizable(True)
|
||||||
col.set_expand(False)
|
col.set_expand(False)
|
||||||
self.tree.append_column(col)
|
self.tree.append_column(col)
|
||||||
|
@ -125,6 +128,8 @@ class FileTransfersWindow:
|
||||||
'pause': gtk.STOCK_MEDIA_PAUSE,
|
'pause': gtk.STOCK_MEDIA_PAUSE,
|
||||||
'continue': gtk.STOCK_MEDIA_PLAY,
|
'continue': gtk.STOCK_MEDIA_PLAY,
|
||||||
'ok': gtk.STOCK_APPLY,
|
'ok': gtk.STOCK_APPLY,
|
||||||
|
'computing': gtk.STOCK_EXECUTE,
|
||||||
|
'hash_error': gtk.STOCK_STOP,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.tree.get_selection().set_mode(gtk.SELECTION_SINGLE)
|
self.tree.get_selection().set_mode(gtk.SELECTION_SINGLE)
|
||||||
|
@ -244,6 +249,21 @@ class FileTransfersWindow:
|
||||||
dialogs.ErrorDialog(_('File transfer stopped'), sectext)
|
dialogs.ErrorDialog(_('File transfer stopped'), sectext)
|
||||||
self.tree.get_selection().unselect_all()
|
self.tree.get_selection().unselect_all()
|
||||||
|
|
||||||
|
def show_hash_error(self, jid, file_props):
|
||||||
|
def on_yes(dummy):
|
||||||
|
# TODO: Request the file to the sender
|
||||||
|
pass
|
||||||
|
|
||||||
|
if file_props['type'] == 'r':
|
||||||
|
file_name = os.path.basename(file_props['file-name'])
|
||||||
|
else:
|
||||||
|
file_name = file_props['name']
|
||||||
|
dialogs.YesNoDialog(('File transfer error'),
|
||||||
|
_('The file %(file)s has been fully received, but it seems to be '
|
||||||
|
'wrongly received.\nDo you want to reload it?') % \
|
||||||
|
{'file': file_name}, on_response_yes=on_yes,
|
||||||
|
type_=gtk.MESSAGE_ERROR)
|
||||||
|
|
||||||
def show_file_send_request(self, account, contact):
|
def show_file_send_request(self, account, contact):
|
||||||
win = gtk.ScrolledWindow()
|
win = gtk.ScrolledWindow()
|
||||||
win.set_shadow_type(gtk.SHADOW_IN)
|
win.set_shadow_type(gtk.SHADOW_IN)
|
||||||
|
@ -449,6 +469,36 @@ class FileTransfersWindow:
|
||||||
file_props['stopped'] = True
|
file_props['stopped'] = True
|
||||||
elif status == 'ok':
|
elif status == 'ok':
|
||||||
file_props['completed'] = True
|
file_props['completed'] = True
|
||||||
|
text = self._format_percent(100)
|
||||||
|
received_size = int(file_props['received-len'])
|
||||||
|
full_size = int(file_props['size'])
|
||||||
|
text += helpers.convert_bytes(received_size) + '/' + \
|
||||||
|
helpers.convert_bytes(full_size)
|
||||||
|
self.model.set(iter_, C_PROGRESS, text)
|
||||||
|
self.model.set(iter_, C_PULSE, gobject.constants.G_MAXINT)
|
||||||
|
elif status == 'computing':
|
||||||
|
self.model.set(iter_, C_PULSE, 1)
|
||||||
|
text = _('Checking file...') + '\n'
|
||||||
|
received_size = int(file_props['received-len'])
|
||||||
|
full_size = int(file_props['size'])
|
||||||
|
text += helpers.convert_bytes(received_size) + '/' + \
|
||||||
|
helpers.convert_bytes(full_size)
|
||||||
|
self.model.set(iter_, C_PROGRESS, text)
|
||||||
|
def pulse():
|
||||||
|
p = self.model.get(iter_, C_PULSE)[0]
|
||||||
|
if p == gobject.constants.G_MAXINT:
|
||||||
|
return False
|
||||||
|
self.model.set(iter_, C_PULSE, p + 1)
|
||||||
|
return True
|
||||||
|
gobject.timeout_add(100, pulse)
|
||||||
|
elif status == 'hash_error':
|
||||||
|
text = _('File error') + '\n'
|
||||||
|
received_size = int(file_props['received-len'])
|
||||||
|
full_size = int(file_props['size'])
|
||||||
|
text += helpers.convert_bytes(received_size) + '/' + \
|
||||||
|
helpers.convert_bytes(full_size)
|
||||||
|
self.model.set(iter_, C_PROGRESS, text)
|
||||||
|
self.model.set(iter_, C_PULSE, gobject.constants.G_MAXINT)
|
||||||
self.model.set(iter_, C_IMAGE, self.get_icon(status))
|
self.model.set(iter_, C_IMAGE, self.get_icon(status))
|
||||||
path = self.model.get_path(iter_)
|
path = self.model.get_path(iter_)
|
||||||
self.select_func(path)
|
self.select_func(path)
|
||||||
|
@ -589,7 +639,10 @@ class FileTransfersWindow:
|
||||||
status = 'stop'
|
status = 'stop'
|
||||||
self.model.set(iter_, 0, self.get_icon(status))
|
self.model.set(iter_, 0, self.get_icon(status))
|
||||||
if transfered_size == full_size:
|
if transfered_size == full_size:
|
||||||
self.set_status(typ, sid, 'ok')
|
if file_props['type'] == 'r':
|
||||||
|
self.set_status(typ, sid, 'computing')
|
||||||
|
else:
|
||||||
|
self.set_status(typ, sid, 'ok')
|
||||||
elif just_began:
|
elif just_began:
|
||||||
path = self.model.get_path(iter_)
|
path = self.model.get_path(iter_)
|
||||||
self.select_func(path)
|
self.select_func(path)
|
||||||
|
@ -655,7 +708,7 @@ class FileTransfersWindow:
|
||||||
file_name = file_props['name']
|
file_name = file_props['name']
|
||||||
text_props = gobject.markup_escape_text(file_name) + '\n'
|
text_props = gobject.markup_escape_text(file_name) + '\n'
|
||||||
text_props += contact.get_shown_name()
|
text_props += contact.get_shown_name()
|
||||||
self.model.set(iter_, 1, text_labels, 2, text_props, C_SID,
|
self.model.set(iter_, 1, text_labels, 2, text_props, C_PULSE, -1, C_SID,
|
||||||
file_props['type'] + file_props['sid'])
|
file_props['type'] + file_props['sid'])
|
||||||
self.set_progress(file_props['type'], file_props['sid'], 0, iter_)
|
self.set_progress(file_props['type'], file_props['sid'], 0, iter_)
|
||||||
if 'started' in file_props and file_props['started'] is False:
|
if 'started' in file_props and file_props['started'] is False:
|
||||||
|
|
|
@ -913,6 +913,12 @@ class Interface:
|
||||||
def __compare_hashes(self, account, file_props):
|
def __compare_hashes(self, account, file_props):
|
||||||
session = gajim.connections[account].get_jingle_session(jid=None,
|
session = gajim.connections[account].get_jingle_session(jid=None,
|
||||||
sid=file_props['session-sid'])
|
sid=file_props['session-sid'])
|
||||||
|
ft_win = self.instances['file_transfers']
|
||||||
|
if not session.file_hash:
|
||||||
|
# We disn't get the hash, sender probably don't support that
|
||||||
|
jid = unicode(file_props['sender'])
|
||||||
|
self.popup_ft_result(account, jid, file_props)
|
||||||
|
ft_win.set_status(file_props['type'], file_props['sid'], 'ok')
|
||||||
h = Hashes()
|
h = Hashes()
|
||||||
try:
|
try:
|
||||||
file_ = open(file_props['file-name'], 'r')
|
file_ = open(file_props['file-name'], 'r')
|
||||||
|
@ -922,8 +928,16 @@ class Interface:
|
||||||
file_.close()
|
file_.close()
|
||||||
# If the hash we received and the hash of the file are the same,
|
# If the hash we received and the hash of the file are the same,
|
||||||
# then the file is not corrupt
|
# then the file is not corrupt
|
||||||
if session.file_hash == hash_:
|
jid = unicode(file_props['sender'])
|
||||||
print "they are te same"
|
if session.file_hash != hash_:
|
||||||
|
self.popup_ft_result(account, jid, file_props)
|
||||||
|
ft_win.set_status(file_props['type'], file_props['sid'], 'ok')
|
||||||
|
else:
|
||||||
|
# wrong hash, we need to get the file again!
|
||||||
|
file_props['error'] = -10
|
||||||
|
self.popup_ft_result(account, jid, file_props)
|
||||||
|
ft_win.set_status(file_props['type'], file_props['sid'],
|
||||||
|
'hash_error')
|
||||||
# End jingle session
|
# End jingle session
|
||||||
if session:
|
if session:
|
||||||
session.end_session()
|
session.end_session()
|
||||||
|
@ -949,7 +963,10 @@ class Interface:
|
||||||
else: # we send a file
|
else: # we send a file
|
||||||
jid = unicode(file_props['receiver'])
|
jid = unicode(file_props['receiver'])
|
||||||
gajim.socks5queue.remove_sender(file_props['sid'], True, True)
|
gajim.socks5queue.remove_sender(file_props['sid'], True, True)
|
||||||
|
self.popup_ft_result(account, jid, file_props)
|
||||||
|
|
||||||
|
def popup_ft_result(self, account, jid, file_props):
|
||||||
|
ft = self.instances['file_transfers']
|
||||||
if helpers.allow_popup_window(account):
|
if helpers.allow_popup_window(account):
|
||||||
if file_props['error'] == 0:
|
if file_props['error'] == 0:
|
||||||
if gajim.config.get('notify_on_file_complete'):
|
if gajim.config.get('notify_on_file_complete'):
|
||||||
|
@ -960,6 +977,8 @@ class Interface:
|
||||||
elif file_props['error'] == -6:
|
elif file_props['error'] == -6:
|
||||||
ft.show_stopped(jid, file_props,
|
ft.show_stopped(jid, file_props,
|
||||||
error_msg=_('Error opening file'))
|
error_msg=_('Error opening file'))
|
||||||
|
elif file_props['error'] == -10:
|
||||||
|
ft.show_hash_error(jid, file_props)
|
||||||
return
|
return
|
||||||
|
|
||||||
msg_type = ''
|
msg_type = ''
|
||||||
|
@ -971,6 +990,9 @@ class Interface:
|
||||||
elif file_props['error'] in (-1, -6):
|
elif file_props['error'] in (-1, -6):
|
||||||
msg_type = 'file-stopped'
|
msg_type = 'file-stopped'
|
||||||
event_type = _('File Transfer Stopped')
|
event_type = _('File Transfer Stopped')
|
||||||
|
elif file_props['error'] == -10:
|
||||||
|
msg_type = 'file-hash-error'
|
||||||
|
event_type = _('File Transfer Failed')
|
||||||
|
|
||||||
if event_type == '':
|
if event_type == '':
|
||||||
# FIXME: ugly workaround (this can happen Gajim sent, Gaim recvs)
|
# FIXME: ugly workaround (this can happen Gajim sent, Gaim recvs)
|
||||||
|
@ -988,16 +1010,20 @@ class Interface:
|
||||||
# get the name of the sender, as it is in the roster
|
# get the name of the sender, as it is in the roster
|
||||||
sender = unicode(file_props['sender']).split('/')[0]
|
sender = unicode(file_props['sender']).split('/')[0]
|
||||||
name = gajim.contacts.get_first_contact_from_jid(account,
|
name = gajim.contacts.get_first_contact_from_jid(account,
|
||||||
sender).get_shown_name()
|
sender).get_shown_name()
|
||||||
filename = os.path.basename(file_props['file-name'])
|
filename = os.path.basename(file_props['file-name'])
|
||||||
if event_type == _('File Transfer Completed'):
|
if event_type == _('File Transfer Completed'):
|
||||||
txt = _('You successfully received %(filename)s from '
|
txt = _('You successfully received %(filename)s from '
|
||||||
'%(name)s.') % {'filename': filename, 'name': name}
|
'%(name)s.') % {'filename': filename, 'name': name}
|
||||||
img_name = 'gajim-ft_done'
|
img_name = 'gajim-ft_done'
|
||||||
else: # ft stopped
|
elif event_type == _('File Transfer Stopped'):
|
||||||
txt = _('File transfer of %(filename)s from %(name)s '
|
txt = _('File transfer of %(filename)s from %(name)s '
|
||||||
'stopped.') % {'filename': filename, 'name': name}
|
'stopped.') % {'filename': filename, 'name': name}
|
||||||
img_name = 'gajim-ft_stopped'
|
img_name = 'gajim-ft_stopped'
|
||||||
|
else: # ft hash error
|
||||||
|
txt = _('File transfer of %(filename)s from %(name)s '
|
||||||
|
'failed.') % {'filename': filename, 'name': name}
|
||||||
|
img_name = 'gajim-ft_stopped'
|
||||||
else:
|
else:
|
||||||
receiver = file_props['receiver']
|
receiver = file_props['receiver']
|
||||||
if hasattr(receiver, 'jid'):
|
if hasattr(receiver, 'jid'):
|
||||||
|
@ -1005,24 +1031,28 @@ class Interface:
|
||||||
receiver = receiver.split('/')[0]
|
receiver = receiver.split('/')[0]
|
||||||
# get the name of the contact, as it is in the roster
|
# get the name of the contact, as it is in the roster
|
||||||
name = gajim.contacts.get_first_contact_from_jid(account,
|
name = gajim.contacts.get_first_contact_from_jid(account,
|
||||||
receiver).get_shown_name()
|
receiver).get_shown_name()
|
||||||
filename = os.path.basename(file_props['file-name'])
|
filename = os.path.basename(file_props['file-name'])
|
||||||
if event_type == _('File Transfer Completed'):
|
if event_type == _('File Transfer Completed'):
|
||||||
txt = _('You successfully sent %(filename)s to %(name)s.')\
|
txt = _('You successfully sent %(filename)s to %(name)s.')\
|
||||||
% {'filename': filename, 'name': name}
|
% {'filename': filename, 'name': name}
|
||||||
img_name = 'gajim-ft_done'
|
img_name = 'gajim-ft_done'
|
||||||
else: # ft stopped
|
elif event_type == _('File Transfer Stopped'):
|
||||||
txt = _('File transfer of %(filename)s to %(name)s '
|
txt = _('File transfer of %(filename)s to %(name)s '
|
||||||
'stopped.') % {'filename': filename, 'name': name}
|
'stopped.') % {'filename': filename, 'name': name}
|
||||||
img_name = 'gajim-ft_stopped'
|
img_name = 'gajim-ft_stopped'
|
||||||
|
else: # ft hash error
|
||||||
|
txt = _('File transfer of %(filename)s to %(name)s '
|
||||||
|
'failed.') % {'filename': filename, 'name': name}
|
||||||
|
img_name = 'gajim-ft_stopped'
|
||||||
path = gtkgui_helpers.get_icon_path(img_name, 48)
|
path = gtkgui_helpers.get_icon_path(img_name, 48)
|
||||||
else:
|
else:
|
||||||
txt = ''
|
txt = ''
|
||||||
path = ''
|
path = ''
|
||||||
|
|
||||||
if gajim.config.get('notify_on_file_complete') and \
|
if gajim.config.get('notify_on_file_complete') and \
|
||||||
(gajim.config.get('autopopupaway') or \
|
(gajim.config.get('autopopupaway') or \
|
||||||
gajim.connections[account].connected in (2, 3)):
|
gajim.connections[account].connected in (2, 3)):
|
||||||
# we want to be notified and we are online/chat or we don't mind
|
# we want to be notified and we are online/chat or we don't mind
|
||||||
# bugged when away/na/busy
|
# bugged when away/na/busy
|
||||||
notify.popup(event_type, jid, account, msg_type, path_to_image=path,
|
notify.popup(event_type, jid, account, msg_type, path_to_image=path,
|
||||||
|
@ -1514,7 +1544,7 @@ class Interface:
|
||||||
no_queue = len(gajim.events.get_events(account, jid)) == 0
|
no_queue = len(gajim.events.get_events(account, jid)) == 0
|
||||||
# type_ can be gc-invitation file-send-error file-error
|
# type_ can be gc-invitation file-send-error file-error
|
||||||
# file-request-error file-request file-completed file-stopped
|
# file-request-error file-request file-completed file-stopped
|
||||||
# jingle-incoming
|
# file-hash-error jingle-incoming
|
||||||
# event_type can be in advancedNotificationWindow.events_list
|
# event_type can be in advancedNotificationWindow.events_list
|
||||||
event_types = {'file-request': 'ft_request',
|
event_types = {'file-request': 'ft_request',
|
||||||
'file-completed': 'ft_finished'}
|
'file-completed': 'ft_finished'}
|
||||||
|
@ -1643,7 +1673,7 @@ class Interface:
|
||||||
w = ctrl.parent_win
|
w = ctrl.parent_win
|
||||||
elif type_ in ('normal', 'file-request', 'file-request-error',
|
elif type_ in ('normal', 'file-request', 'file-request-error',
|
||||||
'file-send-error', 'file-error', 'file-stopped', 'file-completed',
|
'file-send-error', 'file-error', 'file-stopped', 'file-completed',
|
||||||
'jingle-incoming'):
|
'file-hash-error', 'jingle-incoming'):
|
||||||
# Get the first single message event
|
# Get the first single message event
|
||||||
event = gajim.events.get_first_event(account, fjid, type_)
|
event = gajim.events.get_first_event(account, fjid, type_)
|
||||||
if not event:
|
if not event:
|
||||||
|
|
|
@ -1917,6 +1917,9 @@ class RosterWindow:
|
||||||
ft.show_stopped(jid, data, error_msg=msg_err)
|
ft.show_stopped(jid, data, error_msg=msg_err)
|
||||||
gajim.events.remove_events(account, jid, event)
|
gajim.events.remove_events(account, jid, event)
|
||||||
return True
|
return True
|
||||||
|
elif event.type_ == 'file-hash-error':
|
||||||
|
ft.show_hash_error(jid, data)
|
||||||
|
gajim.events.remove_events(account, jid, event)
|
||||||
elif event.type_ == 'file-completed':
|
elif event.type_ == 'file-completed':
|
||||||
ft.show_completed(jid, data)
|
ft.show_completed(jid, data)
|
||||||
gajim.events.remove_events(account, jid, event)
|
gajim.events.remove_events(account, jid, event)
|
||||||
|
|
Loading…
Reference in New Issue