umbra.ui.inputAccelerators — Umbra 1.0.4 documentation

### Navigation

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

# Source code for umbra.ui.inputAccelerators

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

    """
    **inputAccelerators.py**

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

    **Description:**
    	This module defines the Application input accelerators objects.

    **Others:**
    """

    #**********************************************************************************************************************
    #***	External imports.
    #**********************************************************************************************************************
    import re
    from PyQt4.QtCore import Qt
    from PyQt4.QtGui import QTextCursor

    #**********************************************************************************************************************
    #***	Internal imports.
    #**********************************************************************************************************************
    import foundations.common
    import foundations.exceptions
    import foundations.strings
    import foundations.verbose

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

    __all__ = ["LOGGER", "getEditorCapability",
    			"indentationPreEventInputAccelerators",
    			"indentationPostEventInputAccelerators",
    			"performCompletion",
    			"completionPreEventInputAccelerators",
    			"completionPostEventInputAccelerators",
    			"symbolsExpandingPreEventInputAccelerators"]

    LOGGER = foundations.verbose.installLogger()

    #**********************************************************************************************************************
    #***	Module classes and definitions.
    #**********************************************************************************************************************
    def getEditorCapability(editor, capability):
    	"""
    	This definition returns given editor capability.

    	:param editor: Document editor. ( QWidget )
    	:param capability: Capability to retrieve. ( String )
    	:return: Capability. ( Object )
    	"""

    	if not hasattr(editor, "language"):
    		return

    	return editor.language.get(capability)

    def indentationPreEventInputAccelerators(editor, event):
    	"""
    	This definition implements indentation pre event input accelerators.

    	:param editor: Document editor. ( QWidget )
    	:param event: Event being handled. ( QEvent )
    	:return: Process event. ( Boolean )
    	"""

    	processEvent = True
    	if not hasattr(editor, "indent"):
    		return processEvent

    	if event.key() == Qt.Key_Tab:
    		processEvent = editor.indent() and False
    	elif event.key() == Qt.Key_Backtab:
    		processEvent = editor.unindent() and False
    	return processEvent

    def indentationPostEventInputAccelerators(editor, event):
    	"""
    	This definition implements indentation post event input accelerators.

    	:param editor: Document editor. ( QWidget )
    	:param event: Event being handled. ( QEvent )
    	:return: Method success. ( Boolean )
    	"""

    	if event.key() in (Qt.Key_Enter, Qt.Key_Return):
    		cursor = editor.textCursor()
    		block = cursor.block().previous()
    		if block.isValid():
    			indent = match = re.match(r"(\s*)", foundations.strings.encode(block.text())).group(1)
    			cursor.insertText(indent)

    			indentationSymbols = getEditorCapability(editor, "indentationSymbols")
    			if not indentationSymbols:
    				return True

    			if not block.text():
    				return True

    			if not foundations.strings.encode(block.text())[-1] in indentationSymbols:
    				return True

    			symbolsPairs = getEditorCapability(editor, "symbolsPairs")
    			if not symbolsPairs:
    				return True

    			cursor.insertText(editor.indentMarker)

    			position = cursor.position()
    			cursor.movePosition(QTextCursor.PreviousBlock, QTextCursor.MoveAnchor)
    			cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.MoveAnchor)
    			cursor.movePosition(QTextCursor.PreviousCharacter, QTextCursor.KeepAnchor)
    			previousCharacter = foundations.strings.encode(cursor.selectedText())
    			cursor.setPosition(position)
    			nextCharacter = editor.getNextCharacter()
    			if previousCharacter in symbolsPairs:
    				if nextCharacter in symbolsPairs.values():
    					cursor.insertBlock()
    					cursor.insertText(match)
    					cursor.movePosition(QTextCursor.PreviousBlock, QTextCursor.MoveAnchor)
    					cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.MoveAnchor)
    					editor.setTextCursor(cursor)
    	return True

    def performCompletion(editor):
    	"""
    	This definition performs the completion on given editor.

    	:param editor: Document editor. ( QWidget )
    	:return: Method success. ( Boolean )
    	"""

    	completionPrefix = editor.getPartialWordUnderCursor()
    	if not completionPrefix:
    		return

    	words = editor.getWords()
    	completionPrefix in words and words.remove(completionPrefix)
    	editor.completer.updateModel(words)
    	editor.completer.setCompletionPrefix(completionPrefix)
    	if editor.completer.completionCount() == 1:
    		completion = editor.completer.completionModel().data(
    					editor.completer.completionModel().index(0, 0)).toString()
    		cursor = editor.textCursor()
    		cursor.insertText(completion[len(completionPrefix):])
    		editor.setTextCursor(cursor)
    	else:
    		popup = editor.completer.popup()
    		popup.setCurrentIndex(editor.completer.completionModel().index(0, 0))

    		completerRectangle = editor.cursorRect()
    		hasattr(editor, "marginArea_LinesNumbers_widget") and completerRectangle.moveTo(
    		completerRectangle.topLeft().x() + editor.marginArea_LinesNumbers_widget.getWidth(),
    		completerRectangle.topLeft().y())
    		completerRectangle.setWidth(editor.completer.popup().sizeHintForColumn(0) + \
    		editor.completer.popup().verticalScrollBar().sizeHint().width())
    		editor.completer.complete(completerRectangle)
    	return True

    def completionPreEventInputAccelerators(editor, event):
    	"""
    	This definition implements completion pre event input accelerators.

    	:param editor: Document editor. ( QWidget )
    	:param event: Event being handled. ( QEvent )
    	:return: Process event. ( Boolean )
    	"""

    	processEvent = True

    	if editor.completer:
    		# TODO: Investigate the slowdown on popup visibility test.
    		if editor.completer.popup().isVisible():
    			if event.key() in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab, Qt.Key_Backtab):
    				event.ignore()
    				processEvent = False
    				return processEvent

    	if event.modifiers() in (Qt.ControlModifier, Qt.MetaModifier) and event.key() == Qt.Key_Space:
    		processEvent = False
    		if not editor.completer:
    			return processEvent

    		performCompletion(editor)

    	return processEvent

    def completionPostEventInputAccelerators(editor, event):
    	"""
    	This definition implements completion post event input accelerators.

    	:param editor: Document editor. ( QWidget )
    	:param event: Event being handled. ( QEvent )
    	:return: Process event. ( Boolean )
    	"""

    	if editor.completer:
    		if editor.completer.popup().isVisible():
    			performCompletion(editor)
    	return True

    def symbolsExpandingPreEventInputAccelerators(editor, event):
    	"""
    	This definition implements symbols expanding pre event input accelerators.

    	:param editor: Document editor. ( QWidget )
    	:param event: Event being handled. ( QEvent )
    	:return: Process event. ( Boolean )
    	"""

    	processEvent = True

    	symbolsPairs = getEditorCapability(editor, "symbolsPairs")
    	if not symbolsPairs:
    		return processEvent

    	text = foundations.strings.encode(event.text())
    	if text in symbolsPairs:
    		cursor = editor.textCursor()
    		if not cursor.hasSelection():
    			cursor.insertText(event.text())
    			# TODO: Provide an efficient code alternative.
    			# position = cursor.position()
    			# cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor)
    			# selectedText = foundations.strings.encode(cursor.selectedText())
    			# cursor.setPosition(position)
    			# if not selectedText.strip():
    			cursor.insertText(symbolsPairs[text])
    			cursor.movePosition(QTextCursor.Left, QTextCursor.MoveAnchor)
    		else:
    			selectionText = cursor.selectedText()
    			cursor.insertText(event.text())
    			cursor.insertText(selectionText)
    			cursor.insertText(symbolsPairs[text])
    		editor.setTextCursor(cursor)
    		processEvent = False

    	if event.key() in (Qt.Key_Backspace,):
    		cursor = editor.textCursor()
    		cursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor)
    		leftText = cursor.selectedText()
    		foundations.common.repeat(lambda: cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor), 2)
    		rightText = cursor.selectedText()

    		if symbolsPairs.get(foundations.strings.encode(leftText)) == foundations.strings.encode(rightText):
    			cursor.deleteChar()
    	return processEvent

### Navigation

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