~ubuntu-branches/ubuntu/hardy/emesene/hardy-proposed

« back to all changes in this revision

Viewing changes to FileTransfer.py

  • Committer: Bazaar Package Importer
  • Author(s): Emilio Pozuelo Monfort
  • Date: 2008-02-06 21:57:05 UTC
  • Revision ID: james.westby@ubuntu.com-20080206215705-d1abf07rdwcaju3p
Tags: upstream-1.0~r1013
ImportĀ upstreamĀ versionĀ 1.0~r1013

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
 
 
3
#   This file is part of emesene.
 
4
#
 
5
#    Emesene is free software; you can redistribute it and/or modify
 
6
#    it under the terms of the GNU General Public License as published by
 
7
#    the Free Software Foundation; either version 2 of the License, or
 
8
#    (at your option) any later version.
 
9
#
 
10
#    emesene is distributed in the hope that it will be useful,
 
11
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
#    GNU General Public License for more details.
 
14
#
 
15
#    You should have received a copy of the GNU General Public License
 
16
#    along with emesene; if not, write to the Free Software
 
17
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 
 
19
import os
 
20
import time
 
21
import gtk
 
22
import gobject
 
23
 
 
24
import emesenelib.common
 
25
import desktop
 
26
 
 
27
class FileTransfer:
 
28
    ''' this class represents one filetransfer'''
 
29
    
 
30
    def __init__(self, controller, p2p, conversation, session, context, sender):
 
31
        '''Constructor
 
32
        The sender parameter accepts the special value "Me", which is not
 
33
        a valid mail, and is used for sent files'''
 
34
 
 
35
        #constants
 
36
        #self.state should always be one of those states
 
37
        self.WAITING = 0
 
38
        self.TRANSFERING = 1
 
39
        self.RECEIVED = 2
 
40
        self.FAILED = 3
 
41
        
 
42
        self.controller = controller
 
43
        self.p2p = p2p
 
44
        self.conversation = conversation
 
45
        self.session = int(session)
 
46
        self.context = context
 
47
        self.sender = sender
 
48
        
 
49
        self.receivedBytes = 0
 
50
        self.state = self.WAITING
 
51
        
 
52
        self.timeAccepted = None
 
53
        
 
54
        if context.preview != '':
 
55
            loader = gtk.gdk.PixbufLoader()
 
56
            loader.write(context.preview)
 
57
            loader.close()
 
58
            
 
59
            self.previewImage = loader.get_pixbuf()
 
60
            loader = None
 
61
        else:
 
62
            self.previewImage = None
 
63
        
 
64
        self.localPath = None
 
65
 
 
66
        if sender == 'Me':
 
67
            self.conversation.appendOutputText(None, \
 
68
                _('Sending %s') % self.context.filename, 'information')
 
69
        else:
 
70
            args = {'mail': self.p2p.mail, 'file': self.context.filename}
 
71
            self.conversation.appendOutputText(None, \
 
72
                _('%(mail)s is sending you %(file)s') % args, \
 
73
                'information')
 
74
        
 
75
        self.signals = []
 
76
        sap = self.signals.append
 
77
        sap(self.p2p.connect('transfer-progress', self.onFtProgress))
 
78
        sap(self.p2p.connect('transfer-failed', self.onFtFailed))
 
79
        sap(self.p2p.connect('file-transfer-complete', self.onFtReceived))
 
80
        if sender == 'Me':
 
81
            sap(self.p2p.connect('file-transfer-accepted', self.onFtAccepted))
 
82
    
 
83
    def disconnect(self):
 
84
        for identifier in self.signals:
 
85
            self.p2p.disconnect(identifier)
 
86
    
 
87
    def getPreviewImage(self):
 
88
        return self.previewImage
 
89
    
 
90
    def getBytes(self):
 
91
        '''returns a tuple with received and total bytes'''
 
92
        return int(self.receivedBytes), int(self.context.file_size)
 
93
    
 
94
    def accept(self):
 
95
        '''accept this transfer'''
 
96
 
 
97
        self.conversation.appendOutputText(None, \
 
98
            _('You have accepted %s') % self.context.filename, \
 
99
            'information')
 
100
 
 
101
        self.p2p.emit('file-transfer-accepted', self.session, self.context,
 
102
            self.sender)
 
103
        self.timeAccepted = time.time()
 
104
        
 
105
        self.state = self.TRANSFERING
 
106
        self.ui.stateChanged()
 
107
 
 
108
    def cancel(self):
 
109
        '''cancel this transfer'''
 
110
 
 
111
        self.conversation.appendOutputText(None,
 
112
            _('You have canceled the transfer of %s') % self.context.filename,
 
113
            'information')
 
114
        
 
115
        self.p2p.emit('file-transfer-canceled', self.session, self.context,
 
116
            self.sender)
 
117
 
 
118
        self.state = self.FAILED
 
119
        self.ui.stateChanged()
 
120
        self.remove()
 
121
    
 
122
    def getElapsedTime(self):
 
123
        '''return the time elapsed since this transfer was accepted'''
 
124
        if not self.timeAccepted:
 
125
            return 0
 
126
        else:
 
127
            return int(time.time()) - int(self.timeAccepted)
 
128
    
 
129
    def getAverageSpeed(self):
 
130
        '''get average file transfer speed (bytes per second)'''
 
131
        time = self.getElapsedTime()
 
132
        if time == 0: # prevent division by zero
 
133
            return 0
 
134
        else: 
 
135
            return self.receivedBytes / time
 
136
    
 
137
    def remove(self):
 
138
        '''remove this transfer'''
 
139
        self.conversation.transfers.remove(self)
 
140
        self.disconnect()
 
141
      
 
142
    def onFtAccepted(self, p2p, session, context, sender):
 
143
        if session != self.session: return
 
144
        
 
145
        self.conversation.appendOutputText(None, \
 
146
            _('Starting transfer of %s') % self.context.filename, \
 
147
            'information')
 
148
 
 
149
        self.timeAccepted = time.time()
 
150
        
 
151
        self.state = self.TRANSFERING
 
152
        self.ui.stateChanged()
 
153
        
 
154
    def onFtProgress(self, switchboard, session, bytes):
 
155
        if session != self.session: return
 
156
 
 
157
        self.receivedBytes = int(bytes)
 
158
        self.ui.updateProgress()
 
159
 
 
160
    def onFtFailed(self, switchboard, session, reason):
 
161
        if session != self.session: return
 
162
        
 
163
        output = _('Transfer of %s failed.') % self.context.filename + ' ' 
 
164
 
 
165
        if reason == 'corrupt':
 
166
            output += _('Some parts of the file are missing')
 
167
        elif reason == 'cancelled':
 
168
            output += _('Interrupted by user')
 
169
        elif reason == 'error':
 
170
            output += _('Transfer error')
 
171
        self.conversation.appendOutputText(None, output, 'error')
 
172
 
 
173
        self.state = self.FAILED
 
174
        self.ui.stateChanged()
 
175
        
 
176
    def onFtReceived(self, p2p, session, context, src, sender):
 
177
        '''called when filetransfer is finished'''
 
178
        if session != self.session: return
 
179
        
 
180
        if sender == 'Me':
 
181
            self.conversation.appendOutputText(None, \
 
182
                _('%s sent successfully') % context.filename, 'information')
 
183
        else:
 
184
            self.conversation.appendOutputText(None, \
 
185
                _('%s received successfully.') % context.filename, \
 
186
                'information')
 
187
        self.conversation.doMessageWaiting(sender)
 
188
        
 
189
        self.receivedBytes = context.file_size
 
190
        self.state = self.RECEIVED
 
191
        self.ui.stateChanged()
 
192
        
 
193
        if sender == 'Me':
 
194
            return
 
195
 
 
196
        # get file dir
 
197
        config = self.controller.config
 
198
        receivedFilesDir = os.path.expanduser(config.user['receivedFilesDir'])
 
199
        
 
200
        # if directory is invalid, save to home directory
 
201
        if not os.path.exists(receivedFilesDir):
 
202
            print receivedFilesDir + ' does not exist. ' \
 
203
                'Saving files to home directory.'
 
204
            receivedFilesDir = os.path.expanduser('~/')
 
205
        
 
206
        name = os.path.join(receivedFilesDir, self.getFilename())
 
207
        
 
208
        num = 0
 
209
        numstr = ''
 
210
        
 
211
        while os.path.exists(name + numstr):
 
212
            num += 1
 
213
            numstr = '.' + str(num)
 
214
 
 
215
        self.localPath = name + numstr
 
216
        
 
217
        # we don't copy because the permissions may be too restrictive
 
218
        # and not match the user preferred umask blah blah
 
219
        dest = open(self.localPath, 'wb')
 
220
        src.seek(0)
 
221
        buffer = src.read(32 * 1024)
 
222
        while buffer:
 
223
            dest.write(buffer)
 
224
            buffer = src.read(32 * 1024)
 
225
        dest.close()
 
226
        src.close()
 
227
    
 
228
    def open(self):
 
229
        '''open received file'''
 
230
        if self.localPath != None:
 
231
            try:
 
232
                desktop.open(self.localPath)
 
233
            except OSError:
 
234
                pass
 
235
    
 
236
    def getFilename(self):
 
237
        return self.context.filename
 
238
    
 
239
    def setBytesReceived(self, bytes):
 
240
        self.receivedBytes = bytes
 
241
        
 
242
    def getFraction(self):
 
243
        '''return the progress of this transfer as a float from 0 to 1'''
 
244
        return float(self.receivedBytes) / float(self.context.file_size)