Source code for pyqtlineeditprogressbar.__init__


"""
.. module:: pyqtlineeditprogressbar

.. moduleauthor: E.R. Uber <eruber@gmail.com>


**PyQtLineEditProgressBar**

This module subclasses Qt's QtLineEdit widget to manage a progress bar
that is displayed as the background color of the QtLineEdit widget.

REFERENCE
---------
The idea for this package came from a `discussion on StackOverflow <https://stackoverflow.com/questions/36972132/how-to-turn-qlineedit-background-into-a-progress-bar>`_.

GPL LICENSE
-----------
This file is part of the PyQtLineEditProgressBar package.

PyQtLineEditProgressBar 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, either version 3 of the License, or
(at your option) any later version.

PyQtLineEditProgressBar 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 PyQtLineEditProgressBar in the file named LICENSE. If not, 
see <https://www.gnu.org/licenses/>.

COPYRIGHT (C) 2019-2020 E.R. Uber (eruber@gmail.com)

Class PyQtLineEditProgressBar
-----------------------------

"""
# ----------------------------------------------------------------------------
# ------------------------ Python Standard Library ---------------------------
# ----------------------------------------------------------------------------
import time

# ----------------------------------------------------------------------------
# -------------------------- Third Party Packages ----------------------------
# ----------------------------------------------------------------------------
from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5 import QtWidgets

from colour import Color  # https://pypi.org/project/colour/

# ----------------------------------------------------------------------------
# ----------------------- Module Global & Constants --------------------------
# ----------------------------------------------------------------------------

# Default Embedded Color Names
DECN = ['green', 'red', 'blue', 'orange', 'yellow', 'purple']

DEFAULT_COLOR_GREEN  = '#aaff7f'   # A pastel mint green
DEFAULT_COLOR_RED    = '#ffa5aa'   # A pastel red
DEFAULT_COLOR_BLUE   = '#b3fff4'   # A pastel blue   
DEFAULT_COLOR_ORANGE = '#ffcc74'   # A pastel orange
DEFAULT_COLOR_YELLOW = '#ffff00'   # A pastel yellow
DEFAULT_COLOR_PURPLE = '#e4b7ff'   # A pastel purple

EMBEDDED_COLORS = {
	DECN[0] : DEFAULT_COLOR_GREEN, 
	DECN[1] : DEFAULT_COLOR_RED,   
	DECN[2] : DEFAULT_COLOR_BLUE,  
	DECN[3] : DEFAULT_COLOR_ORANGE,
	DECN[4] : DEFAULT_COLOR_YELLOW,
	DECN[5] : DEFAULT_COLOR_PURPLE,
}

DEFAULT_COLOR_NAME = DECN[0]

STARTS_EMPTY_FILLS_LEFT_TO_RIGHT  = 'starts-empty-fills-left-to-right'
STARTS_EMPTY_FILLS_RIGHT_TO_LEFT  = 'starts-empty-fills-right-to-left'
STARTS_FULL_EMPTIES_LEFT_TO_RIGHT = 'starts-filled-empties-left-to-right'
STARTS_FULL_EMPTIES_RIGHT_TO_LEFT = 'starts-filled-empties-right-to-left'

BEHAVIORS = [STARTS_EMPTY_FILLS_LEFT_TO_RIGHT,  STARTS_EMPTY_FILLS_RIGHT_TO_LEFT,
			 STARTS_FULL_EMPTIES_LEFT_TO_RIGHT, STARTS_FULL_EMPTIES_RIGHT_TO_LEFT]

LEFT_2_RIGHT = [STARTS_EMPTY_FILLS_LEFT_TO_RIGHT, STARTS_FULL_EMPTIES_LEFT_TO_RIGHT]
RIGHT_2_LEFT = [STARTS_EMPTY_FILLS_RIGHT_TO_LEFT, STARTS_FULL_EMPTIES_RIGHT_TO_LEFT]

BEHAVIOR_MAP = { # init_value, set_color_at_1, set_color_at_3, delta_sign
	BEHAVIORS[0] : [0.001, -0.001,  0.001,  1],  # Count up
	BEHAVIORS[1] : [0.999,  0.001, -0.001, -1],  # Count up
	BEHAVIORS[2] : [0.001,  0.001, -0.001,  1],  # Count down
	BEHAVIORS[3] : [0.999, -0.001,  0.001, -1],  # Count down
}

DEFAULT_BEHAVIOR = STARTS_EMPTY_FILLS_LEFT_TO_RIGHT

# ----------------------------------------------------------------------------
# --------------------- Module Classes & Functions ---------------------------
# ----------------------------------------------------------------------------
# https://doc.qt.io/qt-5/qlineedit.html
[docs]class PyQtLineEditProgressBar(QtWidgets.QLineEdit):
[docs] def __init__(self, contents=None, parent=None, read_only=True, progressbar_color=EMBEDDED_COLORS[DECN[0]], behavior=DEFAULT_BEHAVIOR, text_for_bounding_rect=None, ): """Constructor for the PyQtLineEditProgressBar Class Parameters ---------- contents : str, optional Text displayed in the LineEdit widget (optional, can be set later with setText() method). parent : widget reference, optional The parent widget. read_only : bool, optional Defaults to True which makes the LineEdit widget read only. progressbar_color : str, optional This must be a string describing a color, such as #1435fe. This field is validated using the `colour package <https://pypi.org/project/colour/>`_. Any color specifier accepted by **colour** will pass input validation. If you're not feeling creative enough to specify your own custom color via the **progressbar_color** parameter, there are six built-in color constants that can be specified here: **pyqtlineeditprogressbar.DEFAULT_COLOR_GREEN** **pyqtlineeditprogressbar.DEFAULT_COLOR_RED** **pyqtlineeditprogressbar.DEFAULT_COLOR_ORANGE** **pyqtlineeditprogressbar.DEFAULT_COLOR_BLUE** **pyqtlineeditprogressbar.DEFAULT_COLOR_YELLOW** **pyqtlineeditprogressbar.DEFAULT_COLOR_PURPLE** If not specified, **DEFAULT_COLOR_GREEN**, is used. See the :ref:`intro_label` for a visual of the colors. behavior : str, optional A rather complicated looking string that identifies one of the four possible behaviors of the progress bar: **pyqtlineeditprogressbar.STARTS_EMPTY_FILLS_LEFT_TO_RIGHT** **pyqtlineeditprogressbar.STARTS_EMPTY_FILLS_RIGHT_TO_LEFT** **pyqtlineeditprogressbar.STARTS_FULL_EMPTIES_LEFT_TO_RIGHT** **pyqtlineeditprogressbar.STARTS_FULL_EMPTIES_RIGHT_TO_LEFT** See the :ref:`intro_label` for a visual of the above four behaviors. text_for_bounding_rect : str, optional If you have trouble in layout sizing the LineEdit widget's width, and the contents of this LineEdit widget have a fixed format, then this parameter may be specified to be used by the overridden sizeHint() method to access the Qt Font Metrics sub-system to specify a width width for the font being used. For example: text_for_bounding_rect=" 888/888 [88] " If not specified, then the standard Qt sizeHint() is called. Returns ------- PyQtLineEditProgressBar object An initialized PyQtLineEditProgressBar object with all the power of a normal QLineEdit widget plus a progressbar!! """ super(PyQtLineEditProgressBar, self).__init__(parent=parent) self._parent = parent self._contents = contents self._text_for_bounding_rect = text_for_bounding_rect self._size_hint_qrect = None if self._contents: self.setText(self._contents) self.setReadOnly(read_only) self.setProgressBarColor(progressbar_color) self.setProgressBarBehavior(behavior) self._update_progress_bar()
# https://doc.qt.io/qtforpython/PySide2/QtGui/QLinearGradient.html#detailed-description # https://doc.qt.io/qt-5/qlineargradient.html#details def _update_progress_bar(self): palette = self.palette() QRectF = QtCore.QRectF(self.rect()) gradient = QtGui.QLinearGradient(QRectF.topLeft(), QRectF.topRight()) # https://doc.qt.io/qt-5/qgradient.html#setColorAt gradient.setColorAt(self._value+self._param_1, QtGui.QColor(self._color)) gradient.setColorAt(self._value, QtGui.QColor('#ffffff')) gradient.setColorAt(self._value+self._param_3, QtGui.QColor('#ffffff')) palette.setBrush(QtGui.QPalette.Base, QtGui.QBrush(gradient)) self.setPalette(palette) def _clear_progress_bar(self): palette = self.palette() QRectF = QtCore.QRectF(self.rect()) gradient = QtGui.QLinearGradient(QRectF.topLeft(), QRectF.topRight()) # https://doc.qt.io/qt-5/qgradient.html#setColorAt gradient.setColorAt(0, QtGui.QColor('#ffffff')) #gradient.setColorAt(value, QtGui.QColor('#ffffff')) gradient.setColorAt(1, QtGui.QColor('#ffffff')) palette.setBrush(QtGui.QPalette.Base, QtGui.QBrush(gradient)) self.setPalette(palette) # ------------------------------------------------------------------------- # QLineEdit Methods that are over-ridden # -------------------------------------------------------------------------
[docs] def sizeHint(self): """This overrides QLineEdit's sizeHint() method only if the constructor parameter **text_for_bounding_rect** is specified. In which case the **text_for_bounding_rect** is used to produce a bounding rectangle that is used to return a QSize item from sizeHint(); otherwise, Qt's standard sizeHint() method is called. Parameters ---------- None Nothing Returns ------- QSize object The width, height size hint for the PyQtLineEditProgressBar widget. """ if self._text_for_bounding_rect: if self._size_hint_qrect: # We cache these rather than doing the expensive font calls # over and over w = self._size_hint_qrect.width() h = self._size_hint_qrect.height() else: metrics = QtGui.QFontMetrics(self.font()) # These are probably the widest integers... self._size_hint_qrect = metrics.boundingRect(self._text_for_bounding_rect) w = self._size_hint_qrect.width() h = self._size_hint_qrect.height() return(QtCore.QSize(w, h)) else: return(super(PyQtLineEditProgressBar, self).sizeHint())
# ------------------------------------------------------------------------- # Public API # -------------------------------------------------------------------------
[docs] def updateProgress(self, delta_float): """This is the method that needs to be called periodically to update the LineEdit's progressbar. Parameters ---------- delta_float : float A float that must be between 0.0 and 1.0. Represents the incremental progress of the progress bar for a single progress bar update cycle. For example, if the progress bar represents 6 seconds of work and its updated every second, then delta_float = 1/6. Returns ------- None Nothing """ if self._progressbar_behavior in LEFT_2_RIGHT: if self._value >= 0.998: self._value = 0.001 elif self._value > 0.9: self._value = 0.999 else: self._value = self._value + (self._delta_sign * delta_float) elif self._progressbar_behavior in RIGHT_2_LEFT: if self._value <= 0.0010: self._value = 0.999 elif self._value < 0.100: self._value = 0.001 else: self._value = self._value + (self._delta_sign * delta_float) if self._value > 0.999: self._value = 0.999 if self._value < 0.001: self._value = 0.001 self._update_progress_bar()
[docs] def removeProgressBar(self): """This method removes the ProgressBar from the LineEdit background. Parameters ---------- None Nothing Returns ------- None Nothing """ self._clear_progress_bar()
[docs] def setProgressBarColor(self, color_text): """Iniitalize the color used for the ProgressBar. Parameters ---------- color_text : str A string describing a color value that is verifiable by the `colour package <https://pypi.org/project/colour/>`_. Returns ------- None Nothing Note ---- If this method detects an invalid **color_text** parameter has been specified, the color will be set to the default color which is **pyqtlineeditprogressbar.DEFAULT_COLOR_GREEN**. """ if isinstance(color_text, str): color_text = color_text.lower() try: c = Color(color_text) self._color = c.hex_l except ValueError: self._color = EMBEDDED_COLORS[DEFAULT_COLOR_NAME] else: self._color = EMBEDDED_COLORS[DEFAULT_COLOR_NAME]
[docs] def getProgressBarColor(self): """Returns the color value associated with the ProgressBar.""" return(self._color)
[docs] def setProgressBarBehavior(self, behavior): """Configures the behavior of the ProgressBar based on the value of the **behavior** parameter. Parameters ---------- behavior: str Must be one of four constant string values that describe the behavior of the ProgressBar: **pyqtlineeditprogressbar.STARTS_EMPTY_FILLS_LEFT_TO_RIGHT** **pyqtlineeditprogressbar.STARTS_EMPTY_FILLS_RIGHT_TO_LEFT** **pyqtlineeditprogressbar.STARTS_FULL_EMPTIES_LEFT_TO_RIGHT** **pyqtlineeditprogressbar.STARTS_FULL_EMPTIES_RIGHT_TO_LEFT** Returns ------- None Nothing Note ---- If the behavior is not one of the four acceptable values, it will be set to the default value of **pyqtlineeditprogressbar.STARTS_EMPTY_FILLS_LEFT_TO_RIGHT**. """ if isinstance(behavior, str): behavior = behavior.lower() if behavior in BEHAVIORS: self._progressbar_behavior = behavior else: self._progressbar_behavior = DEFAULT_BEHAVIOR else: self._progressbar_behavior = DEFAULT_BEHAVIOR self._value, self._param_1, self._param_3, self._delta_sign = BEHAVIOR_MAP[self._progressbar_behavior]
[docs] def getBehavior(self): """Returns the how the ProgressBar is configured to behave. Parameters ---------- None Nothing Returns ------- str A string describing how the ProgressBar is configured to behave. It will be one four string values: **pyqtlineeditprogressbar.STARTS_EMPTY_FILLS_LEFT_TO_RIGHT** **pyqtlineeditprogressbar.STARTS_EMPTY_FILLS_RIGHT_TO_LEFT** **pyqtlineeditprogressbar.STARTS_FULL_EMPTIES_LEFT_TO_RIGHT** **pyqtlineeditprogressbar.STARTS_FULL_EMPTIES_RIGHT_TO_LEFT** """ return(self._progressbar_behavior)
[docs] def getValue(self): """Returns the current value of the ProgressBar, which is between 0.0 and 1.0. Parameters ---------- None Nothing Returns ------- float Current value of the ProgressBar, between 0.0 and 1.0. """ return(self._value)