#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# PCEF - PySide Code Editing framework
# Copyright 2013, Colin Duquesnoy <colin.duquesnoy@gmail.com>
#
# This software is released under the LGPLv3 license.
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Contains the bases classes of the project:
- StyledObject
- Mode
- Panel
- CodeEdit
- QCodeEditorBase
"""
import logging
import weakref
from PySide.QtCore import Qt
from PySide.QtGui import QWidget
from PySide.QtGui import QBoxLayout
from PySide.QtGui import QTextEdit
from PySide.QtGui import QFont
from PySide.QtGui import QTextCursor
from PySide.QtGui import QColor
from PySide.QtGui import QTextCharFormat
from PySide.QtGui import QTextFormat
from pcef.style import StyledObject
from pcef.ui import editor_ui
[docs]class EditorExtension(StyledObject):
"""
Base class for editor extension. An extension is a "thing" that can be installed on the QCodeEditorWidget
to add new behaviours.
An editor extension is a :class:`pcef.style.StyledObject` as some extension might need to get access to the editor
style and to update their brushes,...
An editor extension is also an object that can be enabled/disabled. Its provides an enable property that
automatically call the abstract method onStateChanged.
"""
def __init__(self, name, description):
"""
Creates the extension.
:param name: Extension name (used as an identifier)
:param description: A description of the extension (mainly used for gui (settings about the extension)).
"""
StyledObject.__init__(self)
#: Extension name
self.name = name
#: Extension description
self.description = description
#: Extension enables state (subclasses must implement _onStateChanged to disconnect their slots to
# disable any actions)
self.__enabled = False
#: Editor instance
self.editor = None
def __str__(self):
return self.name
[docs] def install(self, editor):
"""
Installs the extension on the editor.
.. warning::
For internal use only. User may needs to override this method to have a chance to connect to the editor
signals.
.. warning::
Don't forget to call **super** when subclassing
:param editor: editor widget instance
:type editor: pcef.core.CodeEditorWidget
"""
self.editor = editor
self._onStyleChanged()
def _onStateChanged(self, state):
"""
Called when the enable state changed.
.. warning: Raises NotImplementedError. Subclasses must override this method to disconnect their slots.
:param state: True = enabled, False = disabled
:type state: bool
"""
raise NotImplementedError()
def __get_enabled(self):
return self.__enabled
def __set_enabled(self, enabled):
if enabled != self.__enabled:
self.__enabled = enabled
self._onStateChanged(enabled)
#: Tells whether the extension is enabled or not
enabled = property(__get_enabled, __set_enabled)
[docs]class Mode(EditorExtension):
"""
Base class for editor modes.
A mode is a :class:`pcef.core.EditorExtension` that is is generally a non-visual element (not a QWidget).
Examples of modes are Code completion, syntax highlighting,...
To use a mode, one must install the mode on the editor widget.
"""
def __init__(self, name, description):
"""
Creates a Mode.
:param name: The mode name
:param description: The mode description
"""
EditorExtension.__init__(self, name, description)
def _onStyleChanged(self):
pass # not all modes need styling, don't force them to implement something they don't need
[docs]class Panel(QWidget, EditorExtension):
"""
Base class for editor Panel widgets.
A Panel is a QWidget and :class:`pcef.core.EditorExtension` that can be installed around the text edit widget.
"""
def __init__(self, name, description, parent):
EditorExtension.__init__(self, name, description)
QWidget.__init__(self, parent)
def _onStateChanged(self, state):
""" Shows/Hides the Panel
:param state: True = enabled, False = disabled
:type state: bool
"""
if state is True:
self.show()
else:
self.hide()
class TextDecoration(QTextEdit.ExtraSelection):
"""
Helper class to quickly create a text decoration.
"""
def __init__(self, cursorOrBlockOrDoc, startPos=None, endPos=None):
"""
Creates a text decoration
:param cursorOrBlockOrDoc: Selection
:type cursorOrBlockOrDoc: QTextCursor or QTextBlock or QTextDocument
:param startPos: Selection start pos
:param endPos: Selection end pos
.. note:: Use the cursor selection if startPos and endPos are none.
"""
QTextEdit.ExtraSelection.__init__(self)
cursor = QTextCursor(cursorOrBlockOrDoc)
if startPos is not None:
cursor.setPosition(startPos)
if endPos is not None:
cursor.setPosition(endPos, QTextCursor.KeepAnchor)
self.cursor = cursor
def setBold(self):
""" Uses bold text """
self.format.setFontWeight(QFont.Bold)
def setForeground(self, color):
""" Sets the foreground color.
:param color: QColor """
self.format.setForeground(color)
def setBackground(self, brush):
""" Sets the background color
:param brush: QBrush
"""
self.format.setBackground(brush)
def setFullWidth(self, flag=True):
""" Sets full width selection
:param flag: True to use full width selection.
"""
self.cursor.clearSelection()
self.format.setProperty(QTextFormat.FullWidthSelection, flag)
def setSpellchecking(self, color=Qt.blue):
""" Underlines text as a spellcheck error.
:param color: color
:type color: QColor
"""
self.format.setUnderlineStyle(QTextCharFormat.SpellCheckUnderline)
self.format.setUnderlineColor(color)
def setError(self, color=Qt.red):
""" Highlights text as a syntax error
:param color: color
:type color: QColor
"""
self.format.setUnderlineStyle(QTextCharFormat.SpellCheckUnderline)
self.format.setUnderlineColor(color)
def setWarning(self, color=QColor("orange")):
"""
Highlights text as a syntax warning
:param color: color
:type color: QColor
"""
self.format.setUnderlineStyle(QTextCharFormat.SpellCheckUnderline)
self.format.setUnderlineColor(color)