#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
**search_QLineEdit.py**
**Platform:**
Windows, Linux, Mac Os X.
**Description:**
Defines the :class:`Search_QLineEdit` class.
**Others:**
"""
#**********************************************************************************************************************
#*** Future imports.
#**********************************************************************************************************************
from __future__ import unicode_literals
#**********************************************************************************************************************
#*** External imports.
#**********************************************************************************************************************
import functools
import os
from PyQt4.QtCore import QString
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QCompleter
from PyQt4.QtGui import QIcon
from PyQt4.QtGui import QLineEdit
from PyQt4.QtGui import QPixmap
from PyQt4.QtGui import QStyle
from PyQt4.QtGui import QToolButton
#**********************************************************************************************************************
#*** Internal imports.
#**********************************************************************************************************************
import foundations.exceptions
import foundations.verbose
import umbra.ui.common
from umbra.ui.widgets.active_QLabel import Active_QLabel
#**********************************************************************************************************************
#*** Module attributes.
#**********************************************************************************************************************
__author__ = "Thomas Mansencal"
__copyright__ = "Copyright (C) 2008 - 2014 - Thomas Mansencal"
__license__ = "GPL V3.0 - http://www.gnu.org/licenses/"
__maintainer__ = "Thomas Mansencal"
__email__ = "[email protected]"
__status__ = "Production"
__all__ = ["LOGGER", "Search_QLineEdit"]
LOGGER = foundations.verbose.installLogger()
#**********************************************************************************************************************
#*** Module classes and definitions.
#**********************************************************************************************************************
[docs]class Search_QLineEdit(QLineEdit):
"""
Defines a `QLineEdit <http://doc.qt.nokia.com/qlinedit.html>`_ subclass providing
a search field with clearing capabilities.
"""
def __init__(self,
parent=None,
uiSearchImage=None,
uiSearchClickedImage=None,
uiClearImage=None,
uiClearClickedImage=None):
"""
Initializes the class.
:param parent: Widget parent.
:type parent: QObject
:param uiSearchImage: Search button image path.
:type uiSearchImage: unicode
:param uiSearchClickedImage: Search button clicked image path.
:type uiSearchClickedImage: unicode
:param uiClearImage: Clear button image path.
:type uiClearImage: unicode
:param uiClearClickedImage: Clear button clicked image path.
:type uiClearClickedImage: unicode
"""
LOGGER.debug("> Initializing '{0}()' class.".format(self.__class__.__name__))
QLineEdit.__init__(self, parent)
# --- Setting class attributes. ---
self.__uiSearchImage = None
self.uiSearchImage = uiSearchImage or umbra.ui.common.getResourcePath("images/Search_Glass.png")
self.__uiSearchClickedImage = None
self.uiSearchClickedImage = uiSearchClickedImage or umbra.ui.common.getResourcePath(
"images/Search_Glass_Clicked.png")
self.__uiClearImage = None
self.uiClearImage = uiClearImage or umbra.ui.common.getResourcePath("images/Search_Clear.png")
self.__uiClearClickedImage = None
self.uiClearClickedImage = uiClearClickedImage or umbra.ui.common.getResourcePath(
"images/Search_Clear_Clicked.png")
self.__searchActiveLabel = Active_QLabel(self,
QPixmap(self.__uiSearchImage),
QPixmap(self.__uiSearchImage),
QPixmap(self.__uiSearchClickedImage))
self.__searchActiveLabel.setObjectName("Search_Field_activeLabel")
self.__searchActiveLabel.showEvent = lambda event: reduce(lambda *args: None,
(self.__setStyleSheet(), Active_QLabel.showEvent(self.__searchActiveLabel, event)))
self.__searchActiveLabel.hideEvent = lambda event: reduce(lambda *args: None,
(self.__setStyleSheet(), Active_QLabel.hideEvent(self.__searchActiveLabel, event)))
self.__clearButton = QToolButton(self)
self.__clearButton.setObjectName("Clear_Field_button")
self.__completer = QCompleter()
self.setCompleter(self.__completer)
self.__completerVisibleItemsCount = 16
Search_QLineEdit.__initializeUi(self)
self.__setClearButtonVisibility(self.text())
# Signals / Slots.
self.__clearButton.clicked.connect(self.clear)
self.textChanged.connect(self.__setClearButtonVisibility)
#******************************************************************************************************************
#*** Attributes properties.
#******************************************************************************************************************
@property
def uiSearchImage(self):
"""
Property for **self.__uiSearchImage** attribute.
:return: self.__uiSearchImage.
:rtype: unicode
"""
return self.__uiSearchImage
@uiSearchImage.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(AssertionError)
def uiSearchImage(self, value):
"""
Setter for **self.__uiSearchImage** attribute.
:param value: Attribute value.
:type value: unicode
"""
if value is not None:
assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format(
"uiSearchImage", value)
assert os.path.exists(value), "'{0}' attribute: '{1}' file doesn't exists!".format("uiSearchImage", value)
self.__uiSearchImage = value
@uiSearchImage.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def uiSearchImage(self):
"""
Deleter for **self.__uiSearchImage** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "uiSearchImage"))
@property
def uiSearchClickedImage(self):
"""
Property for **self.__uiSearchClickedImage** attribute.
:return: self.__uiSearchClickedImage.
:rtype: unicode
"""
return self.__uiSearchClickedImage
@uiSearchClickedImage.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(AssertionError)
def uiSearchClickedImage(self, value):
"""
Setter for **self.__uiSearchClickedImage** attribute.
:param value: Attribute value.
:type value: unicode
"""
if value is not None:
assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format(
"uiSearchClickedImage", value)
assert os.path.exists(value), "'{0}' attribute: '{1}' file doesn't exists!".format(
"uiSearchClickedImage", value)
self.__uiSearchClickedImage = value
@uiSearchClickedImage.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def uiSearchClickedImage(self):
"""
Deleter for **self.__uiSearchClickedImage** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "uiSearchClickedImage"))
@property
def uiClearImage(self):
"""
Property for **self.__uiClearImage** attribute.
:return: self.__uiClearImage.
:rtype: unicode
"""
return self.__uiClearImage
@uiClearImage.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(AssertionError)
def uiClearImage(self, value):
"""
Setter for **self.__uiClearImage** attribute.
:param value: Attribute value.
:type value: unicode
"""
if value is not None:
assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format(
"uiClearImage", value)
assert os.path.exists(value), "'{0}' attribute: '{1}' file doesn't exists!".format(
"uiClearImage", value)
self.__uiClearImage = value
@uiClearImage.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def uiClearImage(self):
"""
Deleter for **self.__uiClearImage** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "uiClearImage"))
@property
def uiClearClickedImage(self):
"""
Property for **self.__uiClearClickedImage** attribute.
:return: self.__uiClearClickedImage.
:rtype: unicode
"""
return self.__uiClearClickedImage
@uiClearClickedImage.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(AssertionError)
def uiClearClickedImage(self, value):
"""
Setter for **self.__uiClearClickedImage** attribute.
:param value: Attribute value.
:type value: unicode
"""
if value is not None:
assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format(
"uiClearClickedImage", value)
assert os.path.exists(value), "'{0}' attribute: '{1}' file doesn't exists!".format(
"uiClearClickedImage", value)
self.__uiClearClickedImage = value
@uiClearClickedImage.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def uiClearClickedImage(self):
"""
Deleter for **self.__uiClearClickedImage** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "uiClearClickedImage"))
@property
def searchActiveLabel(self):
"""
Property for **self.__searchActiveLabel** attribute.
:return: self.__searchActiveLabel.
:rtype: QPushButton
"""
return self.__searchActiveLabel
@searchActiveLabel.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
def searchActiveLabel(self, value):
"""
Setter for **self.__searchActiveLabel** attribute.
:param value: Attribute value.
:type value: QPushButton
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "searchActiveLabel"))
@searchActiveLabel.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def searchActiveLabel(self):
"""
Deleter for **self.__searchActiveLabel** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "searchActiveLabel"))
@property
def clearButton(self):
"""
Property for **self.__clearButton** attribute.
:return: self.__clearButton.
:rtype: QPushButton
"""
return self.__clearButton
@clearButton.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
def clearButton(self, value):
"""
Setter for **self.__clearButton** attribute.
:param value: Attribute value.
:type value: QPushButton
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "clearButton"))
@clearButton.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
@property
def completer(self):
"""
Property for **self.__completer** attribute.
:return: self.__completer.
:rtype: QCompleter
"""
return self.__completer
@completer.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
def completer(self, value):
"""
Setter for **self.__completer** attribute.
:param value: Attribute value.
:type value: QCompleter
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "completer"))
@completer.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def completer(self):
"""
Deleter for **self.__completer** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "completer"))
@property
def completerVisibleItemsCount(self):
"""
Property for **self.__completerVisibleItemsCount** attribute.
:return: self.__completerVisibleItemsCount.
:rtype: int
"""
return self.__completerVisibleItemsCount
@completerVisibleItemsCount.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
def completerVisibleItemsCount(self, value):
"""
Setter for **self.__completerVisibleItemsCount** attribute.
:param value: Attribute value.
:type value: int
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "completerVisibleItemsCount"))
@completerVisibleItemsCount.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def completerVisibleItemsCount(self):
"""
Deleter for **self.__completerVisibleItemsCount** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "completerVisibleItemsCount"))
#******************************************************************************************************************
#*** Class methods.
#******************************************************************************************************************
[docs] def resizeEvent(self, event):
"""
Reimplements the :meth:`QLineEdit.QResizeEvent` method.
:param event: Resize event.
:type event: QResizeEvent
"""
frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth)
searchActiveLabelSize = self.__searchActiveLabel.sizeHint()
self.__searchActiveLabel.move(self.rect().left() + frameWidth,
(self.rect().bottom() - searchActiveLabelSize.height()) / 2 + frameWidth / 2)
clearButtonSize = self.__clearButton.sizeHint()
self.__clearButton.move(self.rect().right() - frameWidth - clearButtonSize.width(),
(self.rect().bottom() - clearButtonSize.height()) / 2 + frameWidth / 2)
def __initializeUi(self):
"""
Initializes the Widget ui.
"""
self.__clearButton.setCursor(Qt.ArrowCursor)
if self.__uiClearImage and self.__uiClearClickedImage:
pixmap = QPixmap(self.__uiClearImage)
clickedPixmap = QPixmap(self.__uiClearClickedImage)
self.__clearButton.setIcon(QIcon(pixmap))
self.__clearButton.setMaximumSize(pixmap.size())
# Signals / Slots.
self.__clearButton.pressed.connect(functools.partial(self.__clearButton.setIcon, QIcon(clickedPixmap)))
self.__clearButton.released.connect(functools.partial(self.__clearButton.setIcon, QIcon(pixmap)))
else:
self.__clearButton.setText("Clear")
self.__setStyleSheet()
frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth)
self.setMinimumSize(max(self.minimumSizeHint().width(), self.__clearButton.sizeHint().height() + frameWidth * 2),
max(self.minimumSizeHint().height(), self.__clearButton.sizeHint().height() + frameWidth * 2))
self.__completer.setCaseSensitivity(Qt.CaseInsensitive)
self.__completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
self.__completer.setMaxVisibleItems(self.__completerVisibleItemsCount)
def __setStyleSheet(self):
"""
Sets the Widget stylesheet.
"""
frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth)
self.setStyleSheet(QString("QLineEdit {{ padding-left: {0}px; padding-right: {1}px; }}".format(
self.__searchActiveLabel.sizeHint().width() if self.__searchActiveLabel.isVisible() else 0 + frameWidth,
self.__clearButton.sizeHint().width() + frameWidth)))
def __setClearButtonVisibility(self, text):
"""
Sets the clear button visibility.
:param text: Current field text.
:type text: QString
"""
if text:
self.__clearButton.show()
else:
self.__clearButton.hide()
# Oncilla: Statement commented by auto-documentation process:
# Oncilla: Statement commented by auto-documentation process: if __name__ == "__main__":
# Oncilla: Statement commented by auto-documentation process: import sys
# Oncilla: Statement commented by auto-documentation process: from PyQt4.QtGui import QGridLayout
# Oncilla: Statement commented by auto-documentation process: from PyQt4.QtGui import QStringListModel
# Oncilla: Statement commented by auto-documentation process: from PyQt4.QtGui import QWidget
# Oncilla: Statement commented by auto-documentation process:
# Oncilla: Statement commented by auto-documentation process: application = umbra.ui.common.getApplicationInstance()
# Oncilla: Statement commented by auto-documentation process:
# Oncilla: Statement commented by auto-documentation process: widget = QWidget()
# Oncilla: Statement commented by auto-documentation process:
# Oncilla: Statement commented by auto-documentation process: gridLayout = QGridLayout()
# Oncilla: Statement commented by auto-documentation process: widget.setLayout(gridLayout)
# Oncilla: Statement commented by auto-documentation process:
# Oncilla: Statement commented by auto-documentation process: search_QLineEditA = Search_QLineEdit()
# Oncilla: Statement commented by auto-documentation process: gridLayout.addWidget(search_QLineEditA)
# Oncilla: Statement commented by auto-documentation process:
# Oncilla: Statement commented by auto-documentation process: search_QLineEditA.completer.setModel(QStringListModel([(letter * 8).title() for letter in map(chr, range(97, 123))]))
# Oncilla: Statement commented by auto-documentation process: search_QLineEditA.setPlaceholderText("Search...")
# Oncilla: Statement commented by auto-documentation process:
# Oncilla: Statement commented by auto-documentation process: search_QLineEditB = Search_QLineEdit()
# Oncilla: Statement commented by auto-documentation process: search_QLineEditB.searchActiveLabel.hide()
# Oncilla: Statement commented by auto-documentation process: gridLayout.addWidget(search_QLineEditB)
# Oncilla: Statement commented by auto-documentation process:
# Oncilla: Statement commented by auto-documentation process: widget.show()
# Oncilla: Statement commented by auto-documentation process: widget.raise_()
# Oncilla: Statement commented by auto-documentation process:
# Oncilla: Statement commented by auto-documentation process: sys.exit(application.exec_())
# Oncilla: Statement commented by auto-documentation process:
# Oncilla: Statement commented by auto-documentation process: