Commit c99ee623 authored by Daniel Brötzmann's avatar Daniel Brötzmann Committed by Philipp Hörist

HTTP Upload Progress: Add ETA

parent ab74eb8d
Pipeline #3705 passed with stages
in 2 minutes and 36 seconds
......@@ -2,14 +2,13 @@
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkGrid" id="grid">
<property name="width_request">300</property>
<object class="GtkBox" id="box">
<property name="width_request">350</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">18</property>
<property name="row_spacing">6</property>
<property name="column_spacing">12</property>
<property name="column_homogeneous">True</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
......@@ -18,8 +17,25 @@
<property name="icon_size">6</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">6</property>
<property name="label">&lt;placeholder&gt;</property>
<style>
<class name="bold"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
......@@ -29,21 +45,111 @@
<property name="label">&lt;file name&gt;</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="progress_label">
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<style>
<class name="dim-label"/>
</style>
<property name="margin_top">6</property>
<property name="row_spacing">6</property>
<property name="column_spacing">12</property>
<property name="column_homogeneous">True</property>
<child>
<object class="GtkLabel" id="progress_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="speed_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="eta_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Progress</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Speed</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Time remaining</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
......@@ -54,41 +160,29 @@
<property name="pulse_step">0.10000000149</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkButton" id="cancel_upload_button">
<property name="label" translatable="yes">Cancel Upload</property>
<property name="label" translatable="yes">_Cancel Upload</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="halign">center</property>
<property name="margin_top">6</property>
<signal name="clicked" handler="on_cancel_upload_button_clicked" swapped="no"/>
<property name="use_underline">True</property>
<signal name="clicked" handler="_on_cancel_upload_button_clicked" swapped="no"/>
<style>
<class name="destructive-action"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">5</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">6</property>
<property name="label">&lt;placeholder&gt;</property>
<style>
<class name="bold"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">6</property>
</packing>
</child>
</object>
......
......@@ -32,13 +32,11 @@ from typing import Tuple # pylint: disable=unused-import
import os
import uuid
import logging
import time
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import GLib
from gajim.common import ged
from gajim.common.i18n import _
from gajim.common.const import ACTIVITIES
from gajim.common.const import MOODS
......@@ -1146,79 +1144,3 @@ class VoIPCallReceivedDialog:
session.reject_content(content)
dialog.destroy()
class ProgressWindow(Gtk.ApplicationWindow):
def __init__(self, file):
Gtk.ApplicationWindow.__init__(self)
self.set_name('HTTPUploadProgressWindow')
self.set_application(app.app)
self.set_position(Gtk.WindowPosition.CENTER)
self.set_show_menubar(False)
self.set_title(_('File Transfer'))
self.event = file.event
self.file = file
self._ui = get_builder('httpupload_progress_dialog.ui')
file_name = os.path.basename(file.path)
self._ui.file_name_label.set_text(file_name)
self._start_time = time.time()
self.add(self._ui.grid)
self.pulse = GLib.timeout_add(100, self._pulse_progressbar)
self.show_all()
self.connect('destroy', self._on_destroy)
self._ui.connect_signals(self)
app.ged.register_event_handler('httpupload-progress', ged.CORE,
self._on_httpupload_progress)
def _on_httpupload_progress(self, obj):
if self.file != obj.file:
return
if obj.status == 'request':
self._ui.label.set_text(_('Requesting HTTP File Upload Slot…'))
elif obj.status == 'close':
self.destroy()
elif obj.status == 'upload':
self._ui.label.set_text(_('Uploading via HTTP File Upload…'))
elif obj.status == 'update':
self.update_progress(obj.seen, obj.total)
elif obj.status == 'encrypt':
self._ui.label.set_text(_('Encrypting file…'))
def _pulse_progressbar(self):
self._ui.progressbar.pulse()
return True
def on_cancel_upload_button_clicked(self, widget):
self.destroy()
def _on_destroy(self, *args):
self.event.set()
if self.pulse:
GLib.source_remove(self.pulse)
app.ged.remove_event_handler('httpupload-progress', ged.CORE,
self._on_httpupload_progress)
def update_progress(self, seen, total):
if self.event.isSet():
return
if self.pulse:
GLib.source_remove(self.pulse)
self.pulse = None
size_total = round(total / (1024 * 1024), 1)
size_progress = round(seen / (1024 * 1024), 1)
time_now = time.time()
mbytes_sec = round(size_progress / (time_now - self._start_time), 1)
self._ui.progressbar.set_fraction(float(seen) / total)
self._ui.progress_label.set_text(
_('%(progress)s of %(total)s MiB sent (%(speed)s MiB/s)') % \
{'progress': str(size_progress),
'total': str(size_total),
'speed': str(mbytes_sec)})
# This file is part of Gajim.
#
# Gajim is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published
# by the Free Software Foundation; version 3 only.
#
# Gajim is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
import os
import time
from gi.repository import Gtk
from gi.repository import GLib
from gajim.common import app
from gajim.common import ged
from gajim.common.i18n import _
from gajim.gtk.util import get_builder
class HTTPUploadProgressWindow(Gtk.ApplicationWindow):
def __init__(self, file):
Gtk.ApplicationWindow.__init__(self)
self.set_name('HTTPUploadProgressWindow')
self.set_application(app.app)
self.set_position(Gtk.WindowPosition.CENTER)
self.set_show_menubar(False)
self.set_title(_('File Transfer'))
self.event = file.event
self.file = file
self._ui = get_builder('httpupload_progress_dialog.ui')
file_name = os.path.basename(file.path)
self._ui.file_name_label.set_text(file_name)
self._start_time = time.time()
self.add(self._ui.box)
self.pulse = GLib.timeout_add(100, self._pulse_progressbar)
self.show_all()
self.connect('destroy', self._on_destroy)
self._ui.connect_signals(self)
app.ged.register_event_handler('httpupload-progress', ged.CORE,
self._on_httpupload_progress)
def _on_httpupload_progress(self, obj):
if self.file != obj.file:
return
if obj.status == 'request':
self._ui.label.set_text(_('Requesting HTTP File Upload Slot…'))
elif obj.status == 'close':
self.destroy()
elif obj.status == 'upload':
self._ui.label.set_text(_('Uploading via HTTP File Upload…'))
elif obj.status == 'update':
self._update_progress(obj.seen, obj.total)
elif obj.status == 'encrypt':
self._ui.label.set_text(_('Encrypting file…'))
def _pulse_progressbar(self):
self._ui.progressbar.pulse()
return True
def _on_cancel_upload_button_clicked(self, widget):
self.destroy()
def _on_destroy(self, *args):
self.event.set()
if self.pulse:
GLib.source_remove(self.pulse)
app.ged.remove_event_handler('httpupload-progress', ged.CORE,
self._on_httpupload_progress)
def _update_progress(self, seen, total):
if self.event.isSet():
return
if self.pulse:
GLib.source_remove(self.pulse)
self.pulse = None
size_total = round(total / (1024 * 1024), 1)
size_progress = round(seen / (1024 * 1024), 1)
time_now = time.time()
mbytes_sec = round(size_progress / (time_now - self._start_time), 1)
eta = self._format_eta(
round((size_total - size_progress) / mbytes_sec))
self._ui.progressbar.set_fraction(float(seen) / total)
self._ui.progress_label.set_text(
_('%(progress)s of %(total)s MiB') % {
'progress': str(size_progress),
'total': str(size_total)})
self._ui.speed_label.set_text(_('%s MiB/s') % str(mbytes_sec))
self._ui.eta_label.set_text(str(eta))
def _format_eta(self, time_):
times = {'minutes': 0, 'seconds': 0}
time_ = int(time_)
times['seconds'] = time_ % 60
if time_ >= 60:
time_ /= 60
times['minutes'] = time_ % 60
return _('%(minutes)s min %(seconds)s sec') % times
......@@ -58,7 +58,6 @@ from gajim import gui_menu_builder
from gajim import dialogs
from gajim import message_control
from gajim.dialog_messages import get_dialog
from gajim.dialogs import ProgressWindow
from gajim.chat_control_base import ChatControlBase
from gajim.chat_control import ChatControl
......@@ -111,6 +110,7 @@ from gajim.gtk.emoji_data import emoji_data
from gajim.gtk.emoji_data import emoji_ascii_data
from gajim.gtk.groupchat_config import GroupchatConfig
from gajim.gtk.filetransfer import FileTransfersWindow
from gajim.gtk.http_upload_progress import HTTPUploadProgressWindow
from gajim.gtk.roster_item_exchange import RosterItemExchangeWindow
from gajim.gtk.subscription_request import SubscriptionRequestWindow
from gajim.gtk.util import get_show_in_roster
......@@ -928,7 +928,7 @@ class Interface:
@staticmethod
def show_httpupload_progress(file):
ProgressWindow(file)
HTTPUploadProgressWindow(file)
def send_httpupload(self, chat_control):
accept_cb = partial(self.on_file_dialog_ok, chat_control)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment