umbra.ui.widgets.codeEditor_QPlainTextEdit — Umbra 1.0.8 documentation

### Navigation

- index
- modules |
- Umbra 1.0.8 documentation »
- Module code »

# Source code for umbra.ui.widgets.codeEditor_QPlainTextEdit

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-

    """
    **codeEditor_QPlainTextEdit.py**

    **Platform:**
    	Windows, Linux, Mac Os X.

    **Description:**
    	| This module defines the :class:`LinesNumbers_QWidget` and :class:`CodeEditor_QPlainTextEdit` classes.
    	| Those objects provides the basics building blocks of a code editor widget.

    **Others:**
    	Portions of the code from codeeditor.py by Roberto Alsina: http://lateral.netmanagers.com.ar/weblog/posts/BB832.html,
    	KhtEditor.py by Benoit Hervier: http://khertan.net/khteditor, Ninja IDE: http://ninja-ide.org/ and
    	Prymatex: https://github.com/D3f0/prymatex/
    """

    #**********************************************************************************************************************
    #***	Future imports.
    #**********************************************************************************************************************
    from __future__ import unicode_literals

    #**********************************************************************************************************************
    #***	External imports.
    #**********************************************************************************************************************
    import re
    from PyQt4.QtCore import QSize
    from PyQt4.QtCore import pyqtSignal
    from PyQt4.QtGui import QBrush
    from PyQt4.QtGui import QColor
    from PyQt4.QtGui import QCompleter
    from PyQt4.QtGui import QFontMetrics
    from PyQt4.QtGui import QPainter
    from PyQt4.QtGui import QPen
    from PyQt4.QtGui import QSyntaxHighlighter
    from PyQt4.QtGui import QTextCursor
    from PyQt4.QtGui import QTextDocument
    from PyQt4.QtGui import QWidget

    #**********************************************************************************************************************
    #***	Internal imports.
    #**********************************************************************************************************************
    import foundations.exceptions
    import foundations.strings
    import foundations.verbose
    import umbra.ui.common
    import umbra.ui.languages
    from umbra.ui.widgets.basic_QPlainTextEdit import Basic_QPlainTextEdit
    from umbra.ui.widgets.basic_QPlainTextEdit import editBlock
    from umbra.ui.widgets.basic_QPlainTextEdit import anchorTextCursor

    #**********************************************************************************************************************
    #***	Module attributes.
    #**********************************************************************************************************************
    __author__ = "Thomas Mansencal"
    __copyright__ = "Copyright (C) 2008 - 2013 - Thomas Mansencal"
    __license__ = "GPL V3.0 - http://www.gnu.org/licenses/"
    __maintainer__ = "Thomas Mansencal"
    __email__ = "thomas.mansencal@gmail.com"
    __status__ = "Production"

    __all__ = ["LOGGER", "LinesNumbers_QWidget",
    		"CodeEditor_QPlainTextEdit"]

    LOGGER = foundations.verbose.installLogger()

    #**********************************************************************************************************************
    #***	Module classes and definitions.
    #**********************************************************************************************************************
    class LinesNumbers_QWidget(QWidget):
    	"""
    	This class is a `QWidget <http://doc.qt.nokia.com/qwidget.html>`_ subclass providing a lines numbers widget.
    	"""

    	def __init__(self, parent, *args, **kwargs):
    		"""
    		.. Sphinx: Statements updated for auto-documentation purpose.

    		:param parent: Object parent. ( QObject )
    		:param \*args: Arguments. ( \* )
    		:param \*\*kwargs: Keywords arguments. ( \*\* )
    		"""

    		LOGGER.debug("> Initializing '{0}()' class.".format(self.__class__.__name__))

    		QWidget.__init__(self, parent, *args, **kwargs)

    		# --- Setting class attributes. ---
    		self.__editor = parent

    		self.__margin = 16
    		self.__separatorWidth = 4
    		self.__backgroundColor = QColor(48, 48, 48)
    		self.__color = QColor(192, 192, 192)
    		self.__separatorColor = QColor(48, 48, 48)

    		self.setEditorViewportMargins(0)

    	#******************************************************************************************************************
    	#***	Attributes properties.
    	#******************************************************************************************************************
    	@property
    	def editor(self):
    		"""
    		This method is the property for **self.__editor** attribute.

    		:return: self.__editor. ( QWidget )
    		"""

    		return self.__editor

    	@editor.setter
    	def editor(self, value):
    		"""
    		This method is the setter method for **self.__editor** attribute.

    		:param value: Attribute value. ( QWidget )
    		"""

    		self.__editor = value

    	@editor.deleter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def editor(self):
    		"""
    		This method is the deleter method for **self.__editor** attribute.
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "editor"))

    	@property
    	def margin(self):
    		"""
    		This method is the property for **self.__margin** attribute.

    		:return: self.__margin. ( Integer )
    		"""

    		return self.__margin

    	@margin.setter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(AssertionError)
    	def margin(self, value):
    		"""
    		This method is the setter method for **self.__margin** attribute.

    		:param value: Attribute value. ( Integer )
    		"""

    		if value is not None:
    			assert type(value) is int, "'{0}' attribute: '{1}' type is not 'int'!".format("margin", value)
    			assert value > 0, "'{0}' attribute: '{1}' need to be exactly positive!".format("margin", value)
    		self.__margin = value

    	@margin.deleter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def margin(self):
    		"""
    		This method is the deleter method for **self.__margin** attribute.
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "margin"))

    	@property
    	def separatorWidth(self):
    		"""
    		This method is the property for **self.__separatorWidth** attribute.

    		:return: self.__separatorWidth. ( Integer )
    		"""

    		return self.__separatorWidth

    	@separatorWidth.setter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(AssertionError)
    	def separatorWidth(self, value):
    		"""
    		This method is the setter method for **self.__separatorWidth** attribute.

    		:param value: Attribute value. ( Integer )
    		"""

    		if value is not None:
    			assert type(value) is int, "'{0}' attribute: '{1}' type is not 'int'!".format("separatorWidth", value)
    			assert value > 0, "'{0}' attribute: '{1}' need to be exactly positive!".format("separatorWidth", value)
    		self.__separatorWidth = value

    	@separatorWidth.deleter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def separatorWidth(self):
    		"""
    		This method is the deleter method for **self.__separatorWidth** attribute.
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "separatorWidth"))

    	@property
    	def backgroundColor(self):
    		"""
    		This method is the property for **self.__backgroundColor** attribute.

    		:return: self.__backgroundColor. ( QColor )
    		"""

    		return self.__backgroundColor

    	@backgroundColor.setter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(AssertionError)
    	def backgroundColor(self, value):
    		"""
    		This method is the setter method for **self.__backgroundColor** attribute.

    		:param value: Attribute value. ( QColor )
    		"""

    		if value is not None:
    			assert type(value) is QColor, "'{0}' attribute: '{1}' type is not 'QColor'!".format("backgroundColor", value)
    		self.__backgroundColor = value

    	@backgroundColor.deleter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def backgroundColor(self):
    		"""
    		This method is the deleter method for **self.__backgroundColor** attribute.
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "backgroundColor"))

    	@property
    	def color(self):
    		"""
    		This method is the property for **self.__color** attribute.

    		:return: self.__color. ( QColor )
    		"""

    		return self.__color

    	@color.setter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(AssertionError)
    	def color(self, value):
    		"""
    		This method is the setter method for **self.__color** attribute.

    		:param value: Attribute value. ( QColor )
    		"""

    		if value is not None:
    			assert type(value) is QColor, "'{0}' attribute: '{1}' type is not 'QColor'!".format("color", value)
    		self.__color = value

    	@color.deleter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def color(self):
    		"""
    		This method is the deleter method for **self.__color** attribute.
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "color"))

    	@property
    	def separatorColor(self):
    		"""
    		This method is the property for **self.__separatorColor** attribute.

    		:return: self.__separatorColor. ( QColor )
    		"""

    		return self.__separatorColor

    	@separatorColor.setter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(AssertionError)
    	def separatorColor(self, value):
    		"""
    		This method is the setter method for **self.__separatorColor** attribute.

    		:param value: Attribute value. ( QColor )
    		"""

    		if value is not None:
    			assert type(value) is QColor, "'{0}' attribute: '{1}' type is not 'QColor'!".format("separatorColor", value)
    		self.__separatorColor = value

    	@separatorColor.deleter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def separatorColor(self):
    		"""
    		This method is the deleter method for **self.__separatorColor** attribute.
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "separatorColor"))

    	#******************************************************************************************************************
    	#***	Class methods.
    	#******************************************************************************************************************
    	def sizeHint(self):
    		"""
    		This method reimplements the :meth:`QWidget.sizeHint` method.

    		:return: Size hint. ( QSize )
    		"""

    		return QSize(self.getWidth(), 0)

    	def paintEvent(self, event):
    		"""
    		This method reimplements the :meth:`QWidget.paintEvent` method.

    		:param event: Event. ( QEvent )
    		"""

    		def __setBold(state):
    			"""
    			This definition sets the current painter font bold state.

    			:return: Definiton success. ( Boolean )
    			"""

    			font = painter.font()
    			font.setBold(state)
    			painter.setFont(font)
    			return True

    		painter = QPainter(self)
    		painter.fillRect(event.rect(), self.__backgroundColor)

    		pen = QPen(QBrush(), self.__separatorWidth)
    		pen.setColor(self.__separatorColor)
    		painter.setPen(pen)
    		topRightCorner = event.rect().topRight()
    		bottomRightCorner = event.rect().bottomRight()
    		painter.drawLine(topRightCorner.x(), topRightCorner.y(), bottomRightCorner.x(), bottomRightCorner.y())
    		painter.setPen(self.__color)

    		viewportHeight = self.__editor.viewport().height()
    		metrics = QFontMetrics(self.__editor.document().defaultFont())
    		currentBlock = self.__editor.document().findBlock(
    			self.__editor.textCursor().position())

    		block = self.__editor.firstVisibleBlock()
    		blockNumber = block.blockNumber()
    		painter.setFont(self.__editor.document().defaultFont())

    		while block.isValid():
    			blockNumber += 1
    			position = self.__editor.blockBoundingGeometry(block).topLeft() + self.__editor.contentOffset()
    			if position.y() > viewportHeight:
    				break

    			if not block.isVisible():
    				continue

    			block == currentBlock and __setBold(True) or __setBold(False)
    			painter.drawText(self.width() - metrics.width(foundations.strings.toString(blockNumber)) - self.__margin / 3,
    							round(position.y() + metrics.ascent() + metrics.descent() - \
    							(self.__editor.blockBoundingRect(block).height() * 8.0 / 100)),
    							foundations.strings.toString(blockNumber))
    			block = block.next()

    		painter.end()
    		QWidget.paintEvent(self, event)

    	def getWidth(self):
    		"""
    		This method returns the Widget target width.

    		:return: Widget target width. ( Integer )
    		"""

    		return self.__margin + \
    		self.__editor.fontMetrics().width(foundations.strings.toString(max(1, self.__editor.blockCount())))

    	def setEditorViewportMargins(self, newBlocksCount):
    		"""
    		This method sets the editor viewport margins.

    		:param newBlocksCount: Updated editor blocks count. ( Integer )
    		:return: Method success. ( Boolean )
    		"""

    		self.__editor.setViewportMargins(self.getWidth(), 0, 0, 0)
    		return True

    	def updateRectangle(self, rectangle, scrollY):
    		"""
    		This method updates the given widget rectangle.

    		:param rectangle: Rectangle to update. ( QRect )
    		:param scrollY: Amount of pixels the viewport was scrolled. ( Integer )
    		:return: Method success. ( Boolean )
    		"""

    		if scrollY:
    			self.scroll(0, scrollY)
    		else:
    			self.update(0, rectangle.y(), self.width(), rectangle.height())

    		if rectangle.contains(self.__editor.viewport().rect()):
    			self.setEditorViewportMargins(0)
    		return True

    	def updateGeometry(self):
    		"""
    		This method updates the widget geometry.

    		:return: Method success. ( Boolean )
    		"""

    		self.setGeometry(self.__editor.contentsRect().left(),
    						self.__editor.contentsRect().top(),
    						self.getWidth(),
    						self.__editor.contentsRect().height())
    		return True

    class CodeEditor_QPlainTextEdit(Basic_QPlainTextEdit):
    	"""
    	This class provides	a code editor base class.
    	"""

    	languageChanged = pyqtSignal()
    	"""
    	This signal is emited by the :class:`Editor` class when :obj:`ComponentsManagerUi.language` class property language
    	is changed. ( pyqtSignal )
    	"""

    	def __init__(self,
    				parent=None,
    				language=umbra.ui.languages.PYTHON_LANGUAGE,
    				indentMarker="\t",
    				indentWidth=4,
    				commentMarker="#",
    				*args,
    				**kwargs):
    		"""
    		.. Sphinx: Statements updated for auto-documentation purpose.

    		:param parent: Widget parent. ( QObject )
    		:param language: Editor language. ( Language )
    		:param indentMarker: Indentation marker. ( String )
    		:param indentWidth: Indentation spaces count. ( Integer )
    		:param commentMarker: Comment marker. ( String )
    		:param \*args: Arguments. ( \* )
    		:param \*\*kwargs: Keywords arguments. ( \*\* )
    		"""

    		LOGGER.debug("> Initializing '{0}()' class.".format(self.__class__.__name__))

    		Basic_QPlainTextEdit.__init__(self, parent, *args, **kwargs)

    		# --- Setting class attributes. ---
    		self.__language = language

    		self.__indentMarker = None
    		self.indentMarker = indentMarker
    		self.__indentWidth = None
    		self.indentWidth = indentWidth
    		self.__commentMarker = None
    		self.commentMarker = commentMarker

    		self.__marginArea_LinesNumbers_widget = None
    		self.__highlighter = None
    		self.__completer = None

    		self.__occurrencesHighlightColor = QColor(80, 80, 80)

    		self.__preInputAccelerators = []
    		self.__postInputAccelerators = []
    		self.__visualAccelerators = []

    		self.__textCursorAnchor = None

    		CodeEditor_QPlainTextEdit.__initializeUi(self)

    	#******************************************************************************************************************
    	#***	Attributes properties.
    	#******************************************************************************************************************
    	@property
    	def language(self):
    		"""
    		This method is the property for **self.__language** attribute.

    		:return: self.__language. ( Language )
    		"""

    		return self.__language

    	@language.setter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def language(self, value):
    		"""
    		This method is the setter method for **self.__language** attribute.

    		:param value: Attribute value. ( Language )
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "language"))

    	@language.deleter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def language(self):
    		"""
    		This method is the deleter method for **self.__language** attribute.
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "language"))

    	@property
    	def indentMarker(self):
    		"""
    		This method is the property for **self.__indentMarker** attribute.

    		:return: self.__indentMarker. ( String )
    		"""

    		return self.__indentMarker

    	@indentMarker.setter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(AssertionError)
    	def indentMarker(self, value):
    		"""
    		This method is the setter method for **self.__indentMarker** attribute.

    		:param value: Attribute value. ( String )
    		"""

    		if value is not None:
    			assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format(
    			"indentMarker", value)
    			assert re.search(r"\s", value), "'{0}' attribute: '{1}' is not a whitespace character!".format(
    			"indentMarker", value)
    		self.__indentMarker = value

    	@indentMarker.deleter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def indentMarker(self):
    		"""
    		This method is the deleter method for **self.__indentMarker** attribute.
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "indentMarker"))

    	@property
    	def indentWidth(self):
    		"""
    		This method is the property for **self.__indentWidth** attribute.

    		:return: self.__indentWidth. ( Integer )
    		"""

    		return self.__indentWidth

    	@indentWidth.setter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(AssertionError)
    	def indentWidth(self, value):
    		"""
    		This method is the setter method for **self.__indentWidth** attribute.

    		:param value: Attribute value. ( Integer )
    		"""

    		if value is not None:
    			assert type(value) is int, "'{0}' attribute: '{1}' type is not 'int'!".format("indentWidth", value)
    		self.__indentWidth = value

    	@indentWidth.deleter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def indentWidth(self):
    		"""
    		This method is the deleter method for **self.__indentWidth** attribute.
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "indentWidth"))

    	@property
    	def commentMarker(self):
    		"""
    		This method is the property for **self.__commentMarker** attribute.

    		:return: self.__commentMarker. ( String )
    		"""

    		return self.__commentMarker

    	@commentMarker.setter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(AssertionError)
    	def commentMarker(self, value):
    		"""
    		This method is the setter method for **self.__commentMarker** attribute.

    		:param value: Attribute value. ( String )
    		"""

    		if value is not None:
    			assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format(
    			"commentMarker", value)
    		self.__commentMarker = value

    	@commentMarker.deleter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def commentMarker(self):
    		"""
    		This method is the deleter method for **self.__commentMarker** attribute.
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "commentMarker"))

    	@property
    	def marginArea_LinesNumbers_widget(self):
    		"""
    		This method is the property for **self.__marginArea_LinesNumbers_widget** attribute.

    		:return: self.__marginArea_LinesNumbers_widget. ( LinesNumbers_QWidget )
    		"""

    		return self.__marginArea_LinesNumbers_widget

    	@marginArea_LinesNumbers_widget.setter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(AssertionError)
    	def marginArea_LinesNumbers_widget(self, value):
    		"""
    		This method is the setter method for **self.__marginArea_LinesNumbers_widget** attribute.

    		:param value: Attribute value. ( LinesNumbers_QWidget )
    		"""

    		if value is not None:
    			assert type(value) is LinesNumbers_QWidget, \
    			"'{0}' attribute: '{1}' type is not 'LinesNumbers_QWidget'!".format("checked", value)
    		self.__marginArea_LinesNumbers_widget = value

    	@marginArea_LinesNumbers_widget.deleter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def marginArea_LinesNumbers_widget(self):
    		"""
    		This method is the deleter method for **self.__marginArea_LinesNumbers_widget** attribute.
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "marginArea_LinesNumbers_widget"))

    	@property
    	def highlighter(self):
    		"""
    		This method is the property for **self.__highlighter** attribute.

    		:return: self.__highlighter. ( QSyntaxHighlighter )
    		"""

    		return self.__highlighter

    	@highlighter.setter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def highlighter(self, value):
    		"""
    		This method is the setter method for **self.__highlighter** attribute.

    		:param value: Attribute value. ( QSyntaxHighlighter )
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "highlighter"))

    	@highlighter.deleter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def highlighter(self):
    		"""
    		This method is the deleter method for **self.__highlighter** attribute.
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "highlighter"))

    	@property
    	def completer(self):
    		"""
    		This method is the property for **self.__completer** attribute.

    		:return: self.__completer. ( QCompleter )
    		"""

    		return self.__completer

    	@completer.setter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def completer(self, value):
    		"""
    		This method is the setter method for **self.__completer** attribute.

    		:param value: Attribute value. ( QCompleter )
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "completer"))

    	@completer.deleter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def completer(self):
    		"""
    		This method is the deleter method for **self.__completer** attribute.
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "completer"))

    	@property
    	def preInputAccelerators(self):
    		"""
    		This method is the property for **self.__preInputAccelerators** attribute.

    		:return: self.__preInputAccelerators. ( Tuple / List )
    		"""

    		return self.__preInputAccelerators

    	@preInputAccelerators.setter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(AssertionError)
    	def preInputAccelerators(self, value):
    		"""
    		This method is the setter method for **self.__preInputAccelerators** attribute.

    		:param value: Attribute value. ( Tuple / List )
    		"""

    		if value is not None:
    			assert type(value) in (tuple, list), "'{0}' attribute: '{1}' type is not 'tuple' or 'list'!".format(
    			"preInputAccelerators", value)
    		self.__preInputAccelerators = value

    	@preInputAccelerators.deleter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def preInputAccelerators(self):
    		"""
    		This method is the deleter method for **self.__preInputAccelerators** attribute.
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "preInputAccelerators"))

    	@property
    	def postInputAccelerators(self):
    		"""
    		This method is the property for **self.__postInputAccelerators** attribute.

    		:return: self.__postInputAccelerators. ( Tuple / List )
    		"""

    		return self.__postInputAccelerators

    	@postInputAccelerators.setter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(AssertionError)
    	def postInputAccelerators(self, value):
    		"""
    		This method is the setter method for **self.__postInputAccelerators** attribute.

    		:param value: Attribute value. ( Tuple / List )
    		"""

    		if value is not None:
    			assert type(value) in (tuple, list), "'{0}' attribute: '{1}' type is not 'tuple' or 'list'!".format(
    			"postInputAccelerators", value)
    		self.__postInputAccelerators = value

    	@postInputAccelerators.deleter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def postInputAccelerators(self):
    		"""
    		This method is the deleter method for **self.__postInputAccelerators** attribute.
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "postInputAccelerators"))

    	@property
    	def visualAccelerators(self):
    		"""
    		This method is the property for **self.__visualAccelerators** attribute.

    		:return: self.__visualAccelerators. ( Tuple / List )
    		"""

    		return self.__visualAccelerators

    	@visualAccelerators.setter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(AssertionError)
    	def visualAccelerators(self, value):
    		"""
    		This method is the setter method for **self.__visualAccelerators** attribute.

    		:param value: Attribute value. ( Tuple / List )
    		"""

    		if value is not None:
    			assert type(value) in (tuple, list), "'{0}' attribute: '{1}' type is not 'tuple' or 'list'!".format(
    			"visualAccelerators", value)
    		self.__visualAccelerators = value

    	@visualAccelerators.deleter
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def visualAccelerators(self):
    		"""
    		This method is the deleter method for **self.__visualAccelerators** attribute.
    		"""

    		raise foundations.exceptions.ProgrammingError(
    		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "visualAccelerators"))

    	#******************************************************************************************************************
    	#***	Class methods.
    	#******************************************************************************************************************
    	def __initializeUi(self):
    		"""
    		This method initializes the Widget ui.
    		"""

    		self.__marginArea_LinesNumbers_widget = LinesNumbers_QWidget(self)

    		self.__setExtraSelections()

    		self.__setLanguageDescription()

    		# Signals / Slots.
    		self.blockCountChanged.connect(self.__marginArea_LinesNumbers_widget.setEditorViewportMargins)
    		self.updateRequest.connect(self.__marginArea_LinesNumbers_widget.updateRectangle)
    		self.cursorPositionChanged.connect(self.__setExtraSelections)

    	def resizeEvent(self, event):
    		"""
    		This method reimplements the :meth:`Basic_QPlainTextEdit.resizeEvent` method.

    		:param event: Event. ( QEvent )
    		"""

    		Basic_QPlainTextEdit.resizeEvent(self, event)
    		self.__marginArea_LinesNumbers_widget.updateGeometry()

    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@editBlock
    	def keyPressEvent(self, event):
    		"""
    		This method reimplements the :meth:`Basic_QPlainTextEdit.keyPressEvent` method.

    		:param event: Event. ( QEvent )
    		"""

    		processEvent = True
    		for accelerator in self.__preInputAccelerators:
    			processEvent *= accelerator(self, event)

    		if not processEvent:
    			return

    		Basic_QPlainTextEdit.keyPressEvent(self, event)

    		for accelerator in self.__postInputAccelerators:
    			accelerator(self, event)

    	def __setExtraSelections(self):
    		"""
    		This method sets current document extra selections.
    		"""

    		self.setExtraSelections(())
    		for accelerator in self.__visualAccelerators:
    			accelerator(self)

    	def __insertCompletion(self, completion):
    		"""
    		This method inserts the completion text in the current document.

    		:param completion: Completion text. ( QString )
    		"""

    		LOGGER.debug("> Inserting '{0}' completion.".format(completion))

    		textCursor = self.textCursor()
    		extra = (completion.length() - self.__completer.completionPrefix().length())
    		textCursor.insertText(completion.right(extra))
    		self.setTextCursor(textCursor)

    	def __setLanguageDescription(self):
    		"""
    		This method sets the language accelerators.
    		"""

    		LOGGER.debug("> Setting language description.")

    		if not self.__language:
    			return

    		if self.__language.highlighter:
    			self.setHighlighter(self.__language.highlighter(self.document(),
    															self.__language.rules,
    															self.__language.theme))
    			self.highlighter.rehighlight()
    		else:
    			self.removeHighlighter()

    		if self.__language.completer:
    			self.setCompleter(self.__language.completer(self.parent(), self.__language.name, self.__language.tokens))
    		else:
    			self.removeCompleter()

    		self.indentMarker = self.__language.indentMarker
    		self.commentMarker = self.__language.commentMarker
    		self.preInputAccelerators = self.__language.preInputAccelerators
    		self.postInputAccelerators = self.__language.postInputAccelerators
    		self.visualAccelerators = self.__language.visualAccelerators

    		color = "rgb({0}, {1}, {2})"
    		background = self.__language.theme.get("default").background()
    		foreground = self.__language.theme.get("default").foreground()
    		self.setStyleSheet(
    		"QPlainTextEdit{{ background-color: {0}; color: {1}; }}".format(color.format(background.color().red(),
    																								background.color().green(),
    																								background.color().blue()),
    																				color.format(foreground.color().red(),
    																							foreground.color().green(),
    																							foreground.color().blue())))

    		self.__tabWidth = self.fontMetrics().width(" " * self.indentWidth)
    		self.setTabStopWidth(self.__tabWidth)

    	def setLanguage(self, language):
    		"""
    		This method sets the language.

    		:param language: Language to set. ( Language )
    		:return: Method success. ( Boolean )
    		"""

    		LOGGER.debug("> Setting editor language to '{0}'.".format(language.name))
    		self.__language = language or  umbra.ui.languages.PYTHON_LANGUAGE
    		self.__setLanguageDescription()
    		self.languageChanged.emit()
    		return True

    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def setHighlighter(self, highlighter):
    		"""
    		This method sets given highlighter as the current document highlighter.

    		:param highlighter: Highlighter. ( QSyntaxHighlighter )
    		:return: Method success. ( Boolean )
    		"""

    		if not issubclass(highlighter.__class__, QSyntaxHighlighter):
    			raise foundations.exceptions.ProgrammingError("{0} | '{1}' is not a 'QSyntaxHighlighter' subclass!".format(
    			self.__class__.__name__, highlighter))

    		if self.__highlighter:
    			self.removeHighlighter()

    		LOGGER.debug("> Setting '{0}' highlighter.".format(highlighter))
    		self.__highlighter = highlighter

    		return True

    	def removeHighlighter(self):
    		"""
    		This method removes current highlighter.

    		:return: Method success. ( Boolean )
    		"""

    		if self.__highlighter:
    			LOGGER.debug("> Removing '{0}' highlighter.".format(self.__highlighter))
    			self.__highlighter.deleteLater()
    			self.__highlighter = None
    		return True

    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
    	def setCompleter(self, completer):
    		"""
    		This method sets given completer as the current completer.

    		:param completer: Completer. ( QCompleter )
    		:return: Method success. ( Boolean )
    		"""

    		if not issubclass(completer.__class__, QCompleter):
    			raise foundations.exceptions.ProgrammingError("{0} | '{1}' is not a 'QCompleter' subclass!".format(
    			self.__class__.__name__, completer))

    		if self.__completer:
    			self.removeCompleter()

    		LOGGER.debug("> Setting '{0}' completer.".format(completer))
    		self.__completer = completer
    		self.__completer.setWidget(self)

    		# Signals / Slots.
    		self.__completer.activated.connect(self.__insertCompletion)

    		return True

    	def removeCompleter(self):
    		"""
    		This method removes current completer.

    		:return: Method success. ( Boolean )
    		"""

    		if self.__completer:
    			LOGGER.debug("> Removing '{0}' completer.".format(self.__completer))
    			# Signals / Slots.
    			self.__completer.activated.disconnect(self.__insertCompletion)

    			self.__completer.deleteLater()
    			self.__completer = None
    		return True

    	def getMatchingSymbolsPairs(self, cursor, openingSymbol, closingSymbol, backward=False):
    		"""
    		This method returns the cursor for matching given symbols pairs.

    		:param cursor: Cursor to match from. ( QTextCursor )
    		:param openingSymbol: Opening symbol. ( String )
    		:param closingSymbol: Closing symbol to match. ( String )
    		:return: Matching cursor. ( QTextCursor )
    		"""

    		if cursor.hasSelection():
    			startPosition = cursor.selectionEnd() if backward else cursor.selectionStart()
    		else:
    			startPosition = cursor.position()

    		flags = QTextDocument.FindFlags()
    		if backward:
    			flags = flags | QTextDocument.FindBackward

    		startCursor = previousStartCursor = cursor.document().find(openingSymbol, startPosition, flags)
    		endCursor = previousEndCursor = cursor.document().find(closingSymbol, startPosition, flags)
    		if backward:
    			while startCursor > endCursor:
    				startCursor = cursor.document().find(openingSymbol, startCursor.selectionStart(), flags)
    				if startCursor > endCursor:
    					endCursor = cursor.document().find(closingSymbol, endCursor.selectionStart(), flags)
    		else:
    			while startCursor < endCursor:
    				startCursor = cursor.document().find(openingSymbol, startCursor.selectionEnd(), flags)
    				if startCursor < endCursor:
    					endCursor = cursor.document().find(closingSymbol, endCursor.selectionEnd(), flags)

    		return endCursor.position() != -1 and endCursor or previousEndCursor

    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@editBlock
    	def indent(self):
    		"""
    		This method indents the document text under cursor.

    		:return: Method success. ( Boolean )
    		"""

    		cursor = self.textCursor()
    		if not cursor.hasSelection():
    			cursor.insertText(self.__indentMarker)
    		else:
    			block = self.document().findBlock(cursor.selectionStart())
    			while True:
    				blockCursor = self.textCursor()
    				blockCursor.setPosition(block.position())
    				blockCursor.insertText(self.__indentMarker)
    				if block.contains(cursor.selectionEnd()):
    					break
    				block = block.next()
    		return True

    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@editBlock
    	def unindent(self):
    		"""
    		This method unindents the document text under cursor.

    		:return: Method success. ( Boolean )
    		"""

    		cursor = self.textCursor()
    		if not cursor.hasSelection():
    			cursor.movePosition(QTextCursor.StartOfBlock)
    			line = foundations.strings.toString(self.document().findBlockByNumber(cursor.blockNumber()).text())
    			indentMarker = re.match(r"({0})".format(self.__indentMarker), line)
    			if indentMarker:
    				foundations.common.repeat(cursor.deleteChar, len(indentMarker.group(1)))
    		else:
    			block = self.document().findBlock(cursor.selectionStart())
    			while True:
    				blockCursor = self.textCursor()
    				blockCursor.setPosition(block.position())
    				indentMarker = re.match(r"({0})".format(self.__indentMarker), block.text())
    				if indentMarker:
    					foundations.common.repeat(blockCursor.deleteChar, len(indentMarker.group(1)))
    				if block.contains(cursor.selectionEnd()):
    					break
    				block = block.next()
    		return True

    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@editBlock
    	def toggleComments(self):
    		"""
    		This method toggles comments on the document selected lines.

    		:return: Method success. ( Boolean )
    		"""

    		if not self.__commentMarker:
    			return True

    		cursor = self.textCursor()
    		if not cursor.hasSelection():
    			cursor.movePosition(QTextCursor.StartOfBlock)
    			line = foundations.strings.toString(self.document().findBlockByNumber(cursor.blockNumber()).text())
    			if line.startswith(self.__commentMarker):
    				foundations.common.repeat(cursor.deleteChar, len(self.__commentMarker))
    			else:
    				cursor.insertText(self.__commentMarker)
    		else:
    			block = self.document().findBlock(cursor.selectionStart())
    			while True:
    				blockCursor = self.textCursor()
    				blockCursor.setPosition(block.position())

    				if foundations.strings.toString(block.text()).startswith(self.__commentMarker):
    					foundations.common.repeat(blockCursor.deleteChar, len(self.__commentMarker))
    				else:
    					blockCursor.insertText(self.__commentMarker)

    				if block.contains(cursor.selectionEnd()):
    					break
    				block = block.next()
    		return True

    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@anchorTextCursor
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@editBlock
    	def removeTrailingWhiteSpaces(self):
    		"""
    		This method removes document trailing white spaces.

    		:return: Method success. ( Boolean )
    		"""

    		cursor = self.textCursor()

    		block = self.document().findBlockByLineNumber(0)
    		while block.isValid():
    			cursor.setPosition(block.position())
    			if re.search(r"\s+$", block.text()):
    				cursor.movePosition(QTextCursor.EndOfBlock)
    				cursor.movePosition(QTextCursor.StartOfBlock, QTextCursor.KeepAnchor)
    				cursor.insertText(foundations.strings.toString(block.text()).rstrip())
    			block = block.next()
    		cursor.movePosition(QTextCursor.End, QTextCursor.MoveAnchor)
    		if not cursor.block().text().isEmpty():
    			cursor.insertText("\n")
    		return True

    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@anchorTextCursor
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@editBlock
    	def convertIndentationToTabs(self):
    		"""
    		This method converts document indentation to tabs.

    		:return: Method success. ( Boolean )
    		"""

    		cursor = self.textCursor()

    		block = self.document().findBlockByLineNumber(0)
    		while block.isValid():
    			cursor.setPosition(block.position())
    			search = re.match(r"^ +", block.text())
    			if search:
    				cursor.movePosition(QTextCursor.StartOfBlock, QTextCursor.MoveAnchor)
    				searchLength = len(search.group(0))
    				foundations.common.repeat(
    				lambda: cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor), searchLength)
    				cursor.insertText(self.__indentMarker * (searchLength / self.__indentWidth))
    			block = block.next()
    		return True

    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@anchorTextCursor
    	#***	Sphinx: Decorator commented for auto-documentation purpose. 	@editBlock
    	def convertIndentationToSpaces(self):
    		"""
    		This method converts document indentation to spaces.

    		:return: Method success. ( Boolean )
    		"""

    		cursor = self.textCursor()

    		block = self.document().findBlockByLineNumber(0)
    		while block.isValid():
    			cursor.setPosition(block.position())
    			search = re.match(r"^\t+", block.text())
    			if search:
    				cursor.movePosition(QTextCursor.StartOfBlock, QTextCursor.MoveAnchor)
    				searchLength = len(search.group(0))
    				foundations.common.repeat(
    				lambda: cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor), searchLength)
    				cursor.insertText(" " * (searchLength * self.__indentWidth))
    			block = block.next()
    		return True

    #**********************************************************************************************************************
    #***	Sphinx: Statements updated for auto-documentation purpose.
    #**********************************************************************************************************************

### Navigation

- index
- modules |
- Umbra 1.0.8 documentation »
- Module code »