1#
2# Copyright 2004, 2005, 2010 Zuza Software Foundation
3#
4# This file is part of translate.
5#
6# translate is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# translate is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, see <http://www.gnu.org/licenses/>.
18
19"""Progress bar utilities for reporting feedback on the progress of an
20application.
21"""
22
23
24class DotsProgressBar:
25    """An ultra-simple progress indicator that just writes a dot for each
26    action
27    """
28
29    def __init__(self):
30        import sys
31
32        self.stderr = sys.stderr
33        self.amount = 0
34
35    def show(self, verbosemessage):
36        """show a dot for progress :-)"""
37        # pylint: disable=W0613
38        self.stderr.write(".")
39        self.stderr.flush()
40
41    def close(self):
42        self.stderr.write("\n")
43        self.stderr.flush()
44
45    def __del__(self):
46        self.close()
47
48
49class NoProgressBar:
50    """An invisible indicator that does nothing."""
51
52    def __init__(self):
53        self.amount = 0
54
55    def show(self, verbosemessage):
56        """show nothing for progress :-)"""
57        pass
58
59    def close(self):
60        pass
61
62
63class ProgressBar:
64    """A plain progress bar that doesn't know very much about output."""
65
66    def __init__(self, minValue=0, maxValue=100, totalWidth=50):
67        self.progBar = "[]"  # This holds the progress bar string
68        self.min = minValue
69        self.max = maxValue
70        self.span = maxValue - minValue
71        self.width = totalWidth
72        self.amount = 0  # When amount == max, we are 100% done
73
74    def __str__(self):
75        """Produces the string representing the progress bar."""
76        if self.amount < self.min:
77            self.amount = self.min
78        if self.amount > self.max:
79            self.amount = self.max
80
81        # Figure out the new percent done, round to an integer
82        diffFromMin = float(self.amount - self.min)
83        percentDone = (diffFromMin / float(self.span)) * 100.0
84        percentDone = round(percentDone)
85        percentDone = int(percentDone)
86
87        # Figure out how many hash bars the percentage should be
88        allFull = self.width - 7
89        numHashes = (percentDone / 100.0) * allFull
90        numHashes = int(round(numHashes))
91
92        # build a progress bar with hashes and spaces
93        self.progBar = "[%s%s] %3d%%" % (
94            "#" * numHashes,
95            " " * (allFull - numHashes),
96            percentDone,
97        )
98        return str(self.progBar)
99
100    def show(self, verbosemessage):
101        """displays the progress bar"""
102        # pylint: disable=W0613
103        print(self)
104
105
106class MessageProgressBar(ProgressBar):
107    """A ProgressBar that just writes out the messages without any progress
108    display
109    """
110
111    def __init__(self, *args, **kwargs):
112        import sys
113
114        self.sys = sys
115        super().__init__(*args, **kwargs)
116
117    def show(self, verbosemessage):
118        self.sys.stderr.write(verbosemessage + "\n")
119        self.sys.stderr.flush()
120
121
122class HashProgressBar(ProgressBar):
123    """A ProgressBar which knows how to go back to the beginning of the line."""
124
125    def __init__(self, *args, **kwargs):
126        import sys
127
128        self.sys = sys
129        super().__init__(*args, **kwargs)
130
131    def show(self, verbosemessage):
132        self.sys.stderr.write(str(self) + "\r")
133        self.sys.stderr.flush()
134
135    def close(self):
136        self.sys.stderr.write("\n")
137        self.sys.stderr.flush()
138
139    def __del__(self):
140        self.close()
141
142
143class VerboseProgressBar(HashProgressBar):
144    def __init__(self, *args, **kwargs):
145        self.lastwidth = 0
146        super().__init__(*args, **kwargs)
147
148    def show(self, verbosemessage):
149        output = str(self)
150        self.sys.stderr.write("\r" + " " * self.lastwidth)
151        self.sys.stderr.write("\r" + verbosemessage + "\n")
152        self.lastwidth = len(output)
153        self.sys.stderr.write("\r" + output)
154        self.sys.stderr.flush()
155
156
157def test(progressbar):
158    import time
159
160    for n in range(progressbar.min, progressbar.max + 1, 5):
161        progressbar.amount = n
162        progressbar.show("Some message")
163        time.sleep(0.2)
164
165
166if __name__ == "__main__":
167    p = HashProgressBar(0, 100, 50)
168    test(p)
169