Commit a3fe2ff6 authored by Cédric Bellegarde's avatar Cédric Bellegarde

Add a global progressbar for sync

parent 853c12b9
Pipeline #85708 passed with stage
in 10 minutes and 58 seconds
......@@ -57,9 +57,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<style>
<class name="progressbar"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
......
......@@ -176,22 +176,29 @@
</child>
<child>
<object class="GtkToggleButton" id="devices_button">
<property name="sensitive">True</property>
<property name="visible">False</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
<property name="valign">center</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Downloads</property>
<signal name="toggled" handler="_on_devices_button_toggled" swapped="no"/>
<child>
<object class="GtkImage">
<object class="GtkOverlay" id="overlay">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">multimedia-player-symbolic</property>
<property name="icon_size">1</property>
<child>
<object class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">multimedia-player-symbolic</property>
</object>
<packing>
<property name="index">-1</property>
</packing>
</child>
</object>
</child>
<style>
<class name="image-button"/>
<class name="devices-button"/>
</style>
</object>
<packing>
......
......@@ -11,7 +11,12 @@
padding: 6px 5px 6px 5px;
}
.progressbar {
.devices-button {
padding: 2px;
min-width: 28px;
}
.progressbar-button {
border: none;
background-color: transparent;
background-image: none;
......@@ -21,17 +26,19 @@
margin-bottom: 0px;
}
.progressbar progress {
.progressbar-button progress {
background-color: @theme_selected_bg_color;
background-image: none;
border: none;
min-height: 4px;
border-radius: 1px;
min-height: 2px;
}
.progressbar trough {
border: none;
background-color: transparent;
background-image: none;
.progressbar-button trough {
border: 1px solid alpha(@theme_fg_color, 0.5);
border-radius: 1px;
min-height: 2px;
}
Gtk.ListBoxRow .loved-button {
......
......@@ -10,7 +10,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from gi.repository import Gtk, Gio, GObject
from gi.repository import Gtk, Gio, GObject, GLib
from lollypop.define import App
from lollypop.utils import is_device
......@@ -26,11 +26,15 @@ class DevicesPopover(Gtk.Popover):
"content-changed": (GObject.SignalFlags.RUN_FIRST, None, (int,)),
}
def __init__(self):
def __init__(self, progressbar):
"""
Init popover
@param progressbar Gtk.ProgressBar
"""
Gtk.Popover.__init__(self)
self.__syncing = 0
self.__timeout_id = None
self.__progressbar = progressbar
self.__listbox = Gtk.ListBox()
self.__listbox.set_margin_start(5)
self.__listbox.set_margin_end(5)
......@@ -63,6 +67,7 @@ class DevicesPopover(Gtk.Popover):
if not d.query_exists():
d.make_directory_with_parents()
widget = DeviceWidget(name, uri)
widget.connect("syncing", self.__on_syncing)
widget.show()
self.__listbox.add(widget)
self.__listbox.show()
......@@ -103,6 +108,7 @@ class DevicesPopover(Gtk.Popover):
else:
icon = None
widget = DeviceWidget(name, uri, icon)
widget.connect("syncing", self.__on_syncing)
widget.show()
self.__listbox.add(widget)
self.__listbox.show()
......@@ -116,9 +122,24 @@ class DevicesPopover(Gtk.Popover):
uri = mount.get_default_location().get_uri()
for widget in self.__listbox.get_children():
if widget.uri == uri:
widget.disconnect_by_func(self.__on_syncing)
widget.destroy()
self.emit("content-changed", len(self.__listbox.get_children()))
def __update_progress(self):
"""
Update progressbar
"""
progress = 0.0
nb_syncs = 0
for row in self.__listbox.get_children():
nb_syncs += 1
progress += row.progress
if nb_syncs:
value = progress / nb_syncs
self.__progressbar.set_fraction(value)
return True
def __on_mount_added(self, vm, mount):
"""
On volume mounter
......@@ -134,3 +155,26 @@ class DevicesPopover(Gtk.Popover):
@param mount as Gio.Mount
"""
self.__remove_device(mount)
def __on_syncing(self, widget, status):
"""
Start/stop progress status
@param widget as Gtk.Widget
@param status as bool
"""
def hide_progress():
if self.__timeout_id is None:
self.__progressbar.hide()
if status:
self.__syncing += 1
else:
self.__syncing -= 1
if self.__syncing > 0 and self.__timeout_id is None:
self.__progressbar.show()
self.__timeout_id = GLib.timeout_add(1000,
self.__update_progress)
elif self.__syncing == 0 and self.__timeout_id is not None:
GLib.timeout_add(1000, hide_progress)
GLib.source_remove(self.__timeout_id)
self.__timeout_id = None
......@@ -13,6 +13,20 @@
from gi.repository import Gtk, GLib
class ButtonProgressBar(Gtk.ProgressBar):
"""
Simple progress bar with width contraint
"""
def __init__(self):
Gtk.ProgressBar.__init__(self)
self.set_property("valign", Gtk.Align.END)
self.get_style_context().add_class("progressbar-button")
def do_get_preferred_width(self):
return (24, 24)
class ProgressBar(Gtk.ProgressBar):
"""
A smart/smooth FIFO progress bar
......
......@@ -201,7 +201,6 @@ class MtpSync(GObject.Object):
"""
GObject.Object.__init__(self)
self.__cancellable = Gio.Cancellable()
self.__cancellable.cancel()
self.__errors_count = 0
self.__on_mtp_files = []
self.__last_error = ""
......@@ -297,20 +296,19 @@ class MtpSync(GObject.Object):
finally:
Logger.debug("Save sync db")
self.__mtp_syncdb.save()
self.__cancellable.cancel()
self.cancel()
if self.__errors_count != 0:
Logger.debug("Sync errors")
GLib.idle_add(self.emit, "sync-errors", self.__last_error)
Logger.debug("Sync finished")
GLib.idle_add(self.emit, "sync-finished")
@property
def cancellable(self):
def cancel(self):
"""
Get cancellable
@return Gio.Cancellable
Cancel sync
"""
return self.__cancellable
Logger.warning("MtpSync::cancel()")
self.__cancellable.cancel()
@property
def db(self):
......@@ -330,7 +328,7 @@ class MtpSync(GObject.Object):
"""
# Max allowed errors
if self.__errors_count > 5:
self.__cancellable.cancel()
self.cancel()
return
try:
func(*args)
......
......@@ -18,6 +18,7 @@ from lollypop.pop_next import NextPopover
from lollypop.pop_appmenu import AppMenuPopover
from lollypop.pop_devices import DevicesPopover
from lollypop.define import App, Shuffle, Repeat
from lollypop.progressbar import ButtonProgressBar
class ToolbarEnd(Gtk.Bin):
......@@ -103,8 +104,12 @@ class ToolbarEnd(Gtk.Bin):
App().player.connect("playlist-changed", self.__on_playlist_changed)
self.__set_shuffle_icon()
button_progress_bar = ButtonProgressBar()
overlay = builder.get_object("overlay")
overlay.add_overlay(button_progress_bar)
overlay.set_overlay_pass_through(button_progress_bar, True)
devices_button = builder.get_object("devices_button")
self.__devices_popover = DevicesPopover()
self.__devices_popover = DevicesPopover(button_progress_bar)
self.__devices_popover.connect(
"closed", self.__on_popover_closed, devices_button)
self.__devices_popover.connect("content-changed",
......
......@@ -11,11 +11,13 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from gi.repository import Gtk, GLib, Gio
from gi.repository import Gtk, GLib, Gio, GObject
from gi.repository.Gio import FILE_ATTRIBUTE_FILESYSTEM_SIZE, \
FILE_ATTRIBUTE_FILESYSTEM_FREE
from gettext import gettext as _
from lollypop.logger import Logger
from lollypop.define import App
from lollypop.sync_mtp import MtpSync
......@@ -26,6 +28,10 @@ class DeviceWidget(Gtk.ListBoxRow):
A device widget for sync
"""
__gsignals__ = {
"syncing": (GObject.SignalFlags.RUN_FIRST, None, (bool,)),
}
def __init__(self, name, uri, icon=None):
"""
Init widget
......@@ -37,12 +43,14 @@ class DeviceWidget(Gtk.ListBoxRow):
self.get_style_context().add_class("background")
self.__name = name
self.__uri = uri
self.__progress = 0
self.__builder = Gtk.Builder()
self.__builder.add_from_resource("/org/gnome/Lollypop/DeviceWidget.ui")
self.__progress = self.__builder.get_object("progress")
self.__progressbar = self.__builder.get_object("progress")
self.__revealer = self.__builder.get_object("revealer")
self.__builder.get_object("name").set_label(self.__name)
self.__combobox = self.__builder.get_object("combobox")
self.__sync_button = self.__builder.get_object("sync_button")
if icon is not None:
device_symbolic = self.__builder.get_object("device-symbolic")
device_symbolic.set_from_gicon(icon, Gtk.IconSize.DND)
......@@ -66,12 +74,20 @@ class DeviceWidget(Gtk.ListBoxRow):
"""
return self.__uri
@property
def progress(self):
"""
Get progress status
@return int
"""
return self.__progress
#######################
# PROTECTED #
#######################
def _on_reveal_button_clicked(self, button):
"""
Show advanced devices options
Show advanced device options
@param button as Gtk.Button
"""
revealed = self.__revealer.get_reveal_child()
......@@ -82,15 +98,22 @@ class DeviceWidget(Gtk.ListBoxRow):
Sync music on device
@param button as Gtk.Button
"""
self.__progress.set_fraction(0)
uri = self.__get_music_uri()
try:
devices = list(App().settings.get_value("devices"))
index = devices.index(self.__name) + 1
except Exception as e:
Logger.warning("DeviceWidget::_on_sync_button_clicked(): %s", e)
index = 1
App().task_helper.run(self.__mtp_sync.sync, uri, index)
if self.__sync_button.get_label() == _("Synchronize"):
self.__progress = 0
uri = self.__get_music_uri()
try:
devices = list(App().settings.get_value("devices"))
index = devices.index(self.__name) + 1
except Exception as e:
Logger.warning("DeviceWidget::_on_sync_button_clicked(): %s",
e)
index = 1
App().task_helper.run(self.__mtp_sync.sync, uri, index)
self.emit("syncing", True)
button.set_label(_("Cancel"))
else:
self.__mtp_sync.cancel()
button.set_sensitive(False)
def _on_convert_toggled(self, widget):
"""
......@@ -224,7 +247,7 @@ class DeviceWidget(Gtk.ListBoxRow):
free = info.get_attribute_uint64(FILE_ATTRIBUTE_FILESYSTEM_FREE)
used = size - free
fraction = 1 * used / size
self.__progress.set_fraction(fraction)
self.__progressbar.set_fraction(fraction)
except Exception as e:
Logger.error("DeviceWiget::__on_filesystem_info(): %s", e)
......@@ -234,12 +257,14 @@ class DeviceWidget(Gtk.ListBoxRow):
@param mtp_sync as MtpSync
@param value as float
"""
self.__progress.set_fraction(value)
self.__progress = value
def __on_sync_finished(self, mtp_sync):
"""
Emit finished signal
@param mtp_sync as MtpSync
"""
self.__progress.set_fraction(0)
self.__calculate_free_space()
self.emit("syncing", False)
self.__progress = 0
self.__sync_button.set_label(_("Synchronize"))
self.__sync_button.set_sensitive(True)
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