1# Copyright (c) 2014-2021 Cedric Bellegarde <cedric.bellegarde@adishatz.org> 2# This program is free software: you can redistribute it and/or modify 3# it under the terms of the GNU General Public License as published by 4# the Free Software Foundation, either version 3 of the License, or 5# (at your option) any later version. 6# This program is distributed in the hope that it will be useful, 7# but WITHOUT ANY WARRANTY; without even the implied warranty of 8# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9# GNU General Public License for more details. 10# You should have received a copy of the GNU General Public License 11# along with this program. If not, see <http://www.gnu.org/licenses/>. 12 13from gi.repository import Gtk, GLib 14 15 16class ButtonProgressBar(Gtk.ProgressBar): 17 """ 18 Simple progress bar with width contraint 19 """ 20 21 def __init__(self): 22 Gtk.ProgressBar.__init__(self) 23 self.set_property("valign", Gtk.Align.END) 24 self.get_style_context().add_class("progressbar-button") 25 26 def do_get_preferred_width(self): 27 return (24, 24) 28 29 30class ProgressBar(Gtk.ProgressBar): 31 """ 32 A smart/smooth FIFO progress bar 33 Many objects can register and must call set_fraction(1) to unregister 34 """ 35 36 def __init__(self): 37 """ 38 Init progress bar 39 """ 40 Gtk.ProgressBar.__init__(self) 41 self.__callers = [] 42 self.__fraction = 0.0 43 self.__pulse_timeout = None 44 self.__progress_running = False 45 46 def add(self, caller): 47 """ 48 Add caller 49 @param caller as Instance 50 """ 51 if caller not in self.__callers: 52 self.__callers.insert(0, caller) 53 54 def set_fraction(self, fraction, caller): 55 """ 56 Set fraction if caller is on top. 57 @param fraction as float 58 @param caller as object 59 """ 60 if not self.__callers: 61 return 62 if self.__pulse_timeout is not None: 63 GLib.source_remove(self.__pulse_timeout) 64 self.__pulse_timeout = None 65 if caller == self.__callers[0]: 66 self.show() 67 self.__fraction = fraction 68 if fraction == 0: 69 Gtk.ProgressBar.set_fraction(self, 0.0) 70 elif not self.__progress_running: 71 self.__progress_running = True 72 self.__progress_update(caller) 73 74 def pulse(self, pulse): 75 """ 76 Make progress bar visible/pulse if pulse is True 77 @param pulse as bool 78 """ 79 # Only pulse if nobody is using the progressbar 80 if self.__callers: 81 return 82 if pulse: 83 self.show() 84 if self.__pulse_timeout is None: 85 self.__pulse_timeout = GLib.timeout_add(500, self.__pulse) 86 else: 87 self.hide() 88 if self.__pulse_timeout is not None: 89 GLib.source_remove(self.__pulse_timeout) 90 self.__pulse_timeout = None 91 92####################### 93# PRIVATE # 94####################### 95 def __reset(self, caller): 96 """ 97 Reset and hide progressbar 98 @param caller as object 99 """ 100 self.hide() 101 self.__fraction = 0.0 102 Gtk.ProgressBar.set_fraction(self, 0.0) 103 self.__progress_running = False 104 self.__callers.remove(caller) 105 106 def __pulse(self): 107 """ 108 Make progress bar pulse while visible 109 @param pulse as bool 110 """ 111 if self.is_visible(): 112 Gtk.ProgressBar.pulse(self) 113 return True 114 else: 115 Gtk.ProgressBar.set_fraction(self, 0.0) 116 self.__pulse_timeout = None 117 return False 118 119 def __progress_update(self, caller): 120 """ 121 Update progressbar smoothly 122 @param caller as object 123 """ 124 if caller != self.__callers[0]: 125 self.__progress_running = False 126 return 127 current = self.get_fraction() 128 if self.__fraction < 1: 129 progress = (self.__fraction - current) / 10 130 else: 131 progress = 0.01 132 if current < self.__fraction: 133 Gtk.ProgressBar.set_fraction(self, current + progress) 134 if current < 1.0: 135 GLib.timeout_add(10, self.__progress_update, caller) 136 else: 137 GLib.timeout_add(1000, self.__reset, caller) 138