text: # -*- coding: utf-8 -*-
  #
  # Copyright © Spyder Project Contributors
  # Licensed under the terms of the MIT License
  # (see spyder/__init__.py for details)
  
  # Third party imports
  from qtpy.QtCore import Property, QSize, Signal, Slot
  from qtpy.QtGui import QColor, QIcon, QPixmap
  from qtpy.QtWidgets import QColorDialog, QHBoxLayout, QLineEdit, QToolButton
  
  # Local imports
  from spyder.py3compat import is_text_string
  
  
  class ColorButton(QToolButton):
      """
      Color choosing push button
      """
      colorChanged = Signal(QColor)
  
      def __init__(self, parent=None):
          QToolButton.__init__(self, parent)
          self.setFixedSize(20, 20)
          self.setIconSize(QSize(12, 12))
          self.clicked.connect(self.choose_color)
          self._color = QColor()
  
      def choose_color(self):
          color = QColorDialog.getColor(self._color, self.parentWidget(),
                                        'Select Color',
                                        QColorDialog.ShowAlphaChannel)
          if color.isValid():
              self.set_color(color)
  
      def get_color(self):
          return self._color
  
      @Slot(QColor)
      def set_color(self, color):
          if color != self._color:
              self._color = color
              self.colorChanged.emit(self._color)
              pixmap = QPixmap(self.iconSize())
              pixmap.fill(color)
              self.setIcon(QIcon(pixmap))
  
      color = Property("QColor", get_color, set_color)
  
  
  def text_to_qcolor(text):
      """
      Create a QColor from specified string
      Avoid warning from Qt when an invalid QColor is instantiated
      """
      color = QColor()
      text = str(text)
      if not is_text_string(text):
          return color
      if text.startswith('#') and len(text)==7:
          correct = '#0123456789abcdef'
          for char in text:
              if char.lower() not in correct:
                  return color
      elif text not in list(QColor.colorNames()):
          return color
      color.setNamedColor(text)
      return color
  
  
  class ColorLayout(QHBoxLayout):
      """Color-specialized QLineEdit layout"""
      def __init__(self, color, parent=None):
          QHBoxLayout.__init__(self)
          assert isinstance(color, QColor)
          self.lineedit = QLineEdit(color.name(), parent)
          fm = self.lineedit.fontMetrics()
          self.lineedit.setMinimumWidth(int(fm.width(color.name()) * 1.2))
          self.lineedit.textChanged.connect(self.update_color)
          self.addWidget(self.lineedit)
          self.colorbtn = ColorButton(parent)
          self.colorbtn.color = color
          self.colorbtn.colorChanged.connect(self.update_text)
          self.addWidget(self.colorbtn)
  
      def update_color(self, text):
          color = text_to_qcolor(text)
          if color.isValid():
              self.colorbtn.color = color
  
      def update_text(self, color):
          self.lineedit.setText(color.name())
  
      def text(self):
          return self.lineedit.text()
  