xpra icon
Bug tracker and wiki

Ticket #2678: file-transfer-progress.patch

File file-transfer-progress.patch, 9.4 KB (added by Antoine Martin, 6 months ago)

work in progress patch

  • xpra/client/gtk_base/gtk_client_base.py

     
    408408        self.file_ask_dialog = getOpenRequestsWindow(self.show_file_upload)
    409409        self.file_ask_dialog.show()
    410410
     411    def transfer_progress_update(self, send=True, transfer_id=0, elapsed=0, progress=0):
     412        fad = self.file_ask_dialog
     413        if fad:
     414            fad.transfer_progress_update(send, transfer_id, elapsed, progress)
    411415
     416
    412417    def accept_data(self, send_id, dtype, url, printit, openit):
    413418        #check if we have accepted this file via the GUI:
    414419        r = self.data_send_requests.pop(send_id, None)
  • xpra/client/gtk_base/open_requests.py

     
    1010
    1111import gi
    1212gi.require_version("Gtk", "3.0")
     13gi.require_version("Gdk", "3.0")
    1314gi.require_version("Pango", "1.0")
    14 from gi.repository import GLib, Gtk, GdkPixbuf, Pango
     15from gi.repository import GLib, Gtk, Gdk, GdkPixbuf, Pango
    1516
    1617from xpra.gtk_common.gobject_compat import register_os_signals
    1718from xpra.util import envint
     
    2930
    3031URI_MAX_WIDTH = envint("XPRA_URI_MAX_WIDTH", 320)
    3132
     33css = b"""
     34progress, trough {
     35  min-height: 30px;
     36}
     37"""
    3238
     39style_provider = Gtk.CssProvider()
     40style_provider.load_from_data(css)
     41
     42Gtk.StyleContext.add_provider_for_screen(
     43    Gdk.Screen.get_default(),
     44    style_provider,
     45    Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
     46)
     47
    3348_instance = None
    3449def getOpenRequestsWindow(show_file_upload_cb=None):
    3550    global _instance
     
    4661        self.table = None
    4762        self.requests = []
    4863        self.expire_labels = {}
     64        self.progress_bars = {}
    4965        self.window = Gtk.Window()
    5066        self.window.set_border_width(20)
    5167        self.window.connect("delete-event", self.close)
     
    162178        hbox = Gtk.HBox()
    163179        def remove_entry(can_close=False):
    164180            self.requests = [x for x in self.requests if x[1]!=send_id]
     181            self.progress_bars.pop(send_id, None)
    165182            if not self.requests and can_close:
    166183                self.close()
    167184            else:
    168185                self.populate_table()
    169186                self.window.resize(1, 1)
     187        def cancel(*_args):
     188            remove_entry(True)
     189            cb_answer(DENY)
     190        cancel_btn = self.btn("Cancel", None, cancel, "close.png")
     191        hbox.pack_start(cancel_btn)
     192        def show_progressbar():
     193            for b in hbox.get_children():
     194                if b!=cancel_btn:
     195                    hbox.remove(b)
     196            pb = Gtk.ProgressBar()
     197            pb.set_size_request(420, 30)
     198            pb.show()
     199            hbox.set_spacing(20)
     200            hbox.pack_start(pb)
     201            self.progress_bars[send_id] = pb
    170202        def ok(*_args):
    171203            remove_entry(False)
    172204            cb_answer(ACCEPT, False)
    173         def okopen(*_args):
    174             remove_entry(True)
    175             cb_answer(ACCEPT, True)
    176205        def remote(*_args):
    177206            remove_entry(True)
    178207            cb_answer(OPEN)
    179         def cancel(*_args):
    180             remove_entry(True)
    181             cb_answer(DENY)
    182         hbox.pack_start(self.btn("Cancel", None, cancel, "close.png"))
     208        def progress(*_args):
     209            cb_answer(ACCEPT)
     210            show_progressbar()
     211        def progressopen(*_args):
     212            cb_answer(OPEN)
     213            show_progressbar()
    183214        if bytestostr(dtype)=="url":
    184215            hbox.pack_start(self.btn("Open Locally", None, ok, "open.png"))
    185216            hbox.pack_start(self.btn("Open on server", None, remote))
    186217        elif printit:
    187             hbox.pack_start(self.btn("Print", None, ok, "printer.png"))
     218            hbox.pack_start(self.btn("Print", None, progress, "printer.png"))
    188219        else:
    189             hbox.pack_start(self.btn("Download", None, ok, "download.png"))
     220            hbox.pack_start(self.btn("Download", None, progress, "download.png"))
    190221            if openit:
    191                 hbox.pack_start(self.btn("Download and Open", None, okopen, "open.png"))
     222                hbox.pack_start(self.btn("Download and Open", None, progressopen, "open.png"))
    192223                hbox.pack_start(self.btn("Open on server", None, remote))
    193224        return hbox
    194225
     
    203234            self.populate_timer = 0
    204235
    205236
     237    def transfer_progress_update(self, send=True, transfer_id=0, elapsed=0, progress=0):
     238        pb = self.progress_bars.get(transfer_id)
     239        log.error("transfer_progress_update%s pb=%s", (send, transfer_id, elapsed, progress), pb)
     240        if progress<0:
     241            #error: remove the transfer
     242            return
     243        if pb:
     244            pb.set_fraction(progress)
     245        if progress==1:
     246            return
     247
    206248    def show(self):
    207249        log("show()")
    208250        self.window.show_all()
  • xpra/net/file_transfer.py

     
    242242            }
    243243        return info
    244244
    245     def check_digest(self, filename, digest, expected_digest, algo="sha1"):
    246         if digest!=expected_digest:
    247             filelog.error("Error: data does not match, invalid %s file digest for '%s'", algo, filename)
    248             filelog.error(" received %s, expected %s", digest, expected_digest)
    249             raise Exception("failed %s digest verification" % algo)
    250         else:
    251             filelog("%s digest matches: %s", algo, digest)
    252245
     246    def digest_mismatch(self, filename, digest, expected_digest, algo="sha1"):
     247        filelog.error("Error: data does not match, invalid %s file digest for '%s'", algo, filename)
     248        filelog.error(" received %s, expected %s", digest, expected_digest)
     249        raise Exception("failed %s digest verification" % algo)
    253250
     251
    254252    def _check_chunk_receiving(self, chunk_id, chunk_no):
    255253        chunk_state = self.receive_chunks_in_progress.get(chunk_id)
    256254        filelog("_check_chunk_receiving(%s, %s) chunk_state=%s", chunk_id, chunk_no, chunk_state)
     
    268266            filelog.error("Error: cannot find the file transfer id '%s'", nonl(bytestostr(chunk_id)))
    269267            self.send("ack-file-chunk", chunk_id, False, "file transfer id not found", chunk)
    270268            return
     269        def progress(v):
     270            start = chunk_state[0]
     271            send_id = chunk_state[-3]
     272            self.transfer_progress_update(False, send_id, elapsed=monotonic_time()-start, progress=v)
    271273        fd = chunk_state[1]
    272274        if chunk_state[-1]+1!=chunk:
    273275            filelog.error("Error: chunk number mismatch, expected %i but got %i", chunk_state[-1]+1, chunk)
     
    274276            self.send("ack-file-chunk", chunk_id, False, "chunk number mismatch", chunk)
    275277            del self.receive_chunks_in_progress[chunk_id]
    276278            os.close(fd)
     279            progress(-1)
    277280            return
    278281        #update chunk number:
    279282        chunk_state[-1] = chunk
     
    293296                os.close(fd)
    294297            except OSError:
    295298                pass
     299            progress(-1)
    296300            return
    297301        self.send("ack-file-chunk", chunk_id, True, "", chunk)
     302        filesize = chunk_state[6]
     303        progress(min(0.9999, written/filesize))
    298304        if has_more:
    299305            timer = chunk_state[-2]
    300306            if timer:
     
    309315        filename, mimetype, printit, openit, filesize, options = chunk_state[2:8]
    310316        if written!=filesize:
    311317            filelog.error("Error: expected a file of %i bytes, got %i", filesize, written)
     318            progress(-1)
    312319            return
    313320        expected_digest = options.get("sha1")
    314         if expected_digest:
    315             self.check_digest(filename, digest.hexdigest(), expected_digest)
     321        if expected_digest and digest.hexdigest()!=expected_digest:
     322            progress(-1)
     323            self.digest_mismatch(filename, digest, expected_digest, "sha1")
     324            return
     325
     326        progress(1)
    316327        start_time = chunk_state[0]
    317328        elapsed = monotonic_time()-start_time
    318329        mimetype = bytestostr(mimetype)
     
    397408                monotonic_time(),
    398409                fd, filename, mimetype,
    399410                printit, openit, filesize,
    400                 options, digest, 0, timer, chunk,
     411                options, digest, 0, send_id,
     412                timer, chunk,
    401413                ]
    402414            self.receive_chunks_in_progress[chunk_id] = chunk_state
    403415            self.send("ack-file-chunk", chunk_id, True, "", chunk)
     
    415427                u = libfn()
    416428                u.update(file_data)
    417429                l("%s digest: %s - expected: %s", algo, u.hexdigest(), digest)
    418                 self.check_digest(basefilename, u.hexdigest(), digest, algo)
     430                if digest!=u.hexdigest():
     431                    self.digest_mismatch(filename, digest, u.hexdigest(), algo)
    419432        check_digest("sha1", hashlib.sha1)
    420433        check_digest("md5", hashlib.md5)
    421434        try:
     
    841854
    842855    def compressed_wrapper(self, datatype, data, level=5):
    843856        raise NotImplementedError()
     857
     858    def transfer_progress_update(self, send=True, transfer_id=0, elapsed=0, progress=0):
     859        #this method is overriden in the gtk client:
     860        filelog("transfer_progress_update%s", (send, transfer_id, elapsed, progress))