Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PythonEditor : Add line numbers #6096

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ Improvements

- Light Editor : Added `is_sphere` column for Cycles lights.
- Windows : Gaffer now uses the TBB memory allocator for significantly better performance.
- Python Editor : Added line numbers

API
---

- MultiLineTextWidget :
- Added the ability to show line numbers by passing `lineNumbers = True` to the constructor.
- Added `setLineNumbersVisible()` and `getLineNumbersVisible()`
- CodeWidget : Added the ability to show line numbers by passing `lineNumbers = True` to the constructor.


1.5.0.0a3 (relative to 1.5.0.0a2)
Expand Down
4 changes: 2 additions & 2 deletions python/GafferUI/CodeWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@

class CodeWidget( GafferUI.MultiLineTextWidget ) :

def __init__( self, text="", editable=True, fixedLineHeight=None, **kw ) :
def __init__( self, text="", editable=True, fixedLineHeight=None, lineNumbers = False, **kw ) :

GafferUI.MultiLineTextWidget.__init__( self, text, editable, fixedLineHeight = fixedLineHeight, wrapMode = self.WrapMode.None_, role = self.Role.Code, **kw )
GafferUI.MultiLineTextWidget.__init__( self, text, editable, fixedLineHeight = fixedLineHeight, wrapMode = self.WrapMode.None_, role = self.Role.Code, lineNumbers = lineNumbers, **kw )

self.__completer = None
self.__completionMenu = None
Expand Down
107 changes: 104 additions & 3 deletions python/GafferUI/MultiLineTextWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@

import Gaffer
import GafferUI
from ._StyleSheet import _styleColors

from Qt import QtGui
from Qt import QtWidgets
Expand All @@ -53,9 +54,9 @@ class MultiLineTextWidget( GafferUI.Widget ) :
WrapMode = enum.Enum( "WrapNode", [ "None_", "Word", "Character", "WordOrCharacter" ] )
Role = enum.Enum( "Role", [ "Text", "Code" ] )

def __init__( self, text="", editable=True, wrapMode=WrapMode.WordOrCharacter, fixedLineHeight=None, role=Role.Text, placeholderText = "", **kw ) :
def __init__( self, text="", editable=True, wrapMode=WrapMode.WordOrCharacter, fixedLineHeight=None, role=Role.Text, placeholderText = "", lineNumbers = False, **kw ) :

GafferUI.Widget.__init__( self, _PlainTextEdit(), **kw )
GafferUI.Widget.__init__( self, _PlainTextEdit( lineNumbers ), **kw )

## \todo This should come from the Style when we get Styles applied to Widgets
# (and not just Gadgets as we have currently).
Expand Down Expand Up @@ -416,13 +417,34 @@ def __drop( self, widget, event ) :
self.insertText( self.__dropText( event.data ) )
return True

class _QLineNumberArea( QtWidgets.QWidget ) :

def __init__( self, codeEditor ) :

assert( isinstance( codeEditor, _PlainTextEdit ) )
QtWidgets.QWidget.__init__( self, codeEditor )

def sizeHint( self ) :

return QtCore.QSize( self.parentWidget().lineNumberAreaWidth(), 0 )

def paintEvent( self, event ) :

self.parentWidget().lineNumberAreaPaintEvent( event )

class _PlainTextEdit( QtWidgets.QPlainTextEdit ) :

def __init__( self, parent = None ) :
def __init__( self, lineNumbers, parent = None ) :

QtWidgets.QPlainTextEdit.__init__( self, parent )

self.__lineNumberAreaWidget = _QLineNumberArea( self )
self.setLineNumbersVisible( lineNumbers )

self.__fixedLineHeight = None

self.blockCountChanged.connect( self.__updateLineNumberAreaWidth )
self.updateRequest.connect( self.__updateLineNumberArea )
self.document().modificationChanged.connect( self.update )

def setFixedLineHeight( self, fixedLineHeight ) :
Expand All @@ -440,6 +462,56 @@ def getFixedLineHeight( self ) :

return self.__fixedLineHeight

def setLineNumbersVisible( self, visible ) :

self.__lineNumbersVisible = visible
self.__lineNumberAreaWidget.setVisible( visible )
self.__updateLineNumberAreaWidth( 0 )

def getLineNumbersVisible( self ) :

return self.__lineNumbersVisible

def lineNumberAreaWidth( self ) :

if not self.getLineNumbersVisible() :
return 0

digits = 1
value = max( 1, self.blockCount() )
while value >= 10 :
value *= 0.1
digits += 1

return 3 + self.fontMetrics().horizontalAdvance( '9' ) * digits

def lineNumberAreaPaintEvent( self, event ) :

block = self.firstVisibleBlock()

top = round( self.blockBoundingGeometry( block ).translated( self.contentOffset() ).top() )
bottom = top + round( self.blockBoundingRect( block ).height() )

width = self.lineNumberAreaWidth()

painter = QtGui.QPainter( self.__lineNumberAreaWidget )
painter.setPen( QtGui.QColor( *( _styleColors["backgroundLight"] ) ) )
painter.setFont( self.property( "font" ) )

while block.isValid() and top <= event.rect().bottom() :
if block.isVisible() :
painter.drawText(
0,
top,
width,
self.fontMetrics().height(),
QtCore.Qt.AlignRight,
str( block.blockNumber() + 1 )
)
block = block.next()
top = bottom
bottom = top + round( self.blockBoundingRect( block ).height() )

def __computeHeight( self, size ) :

fixedLineHeight = self.getFixedLineHeight()
Expand Down Expand Up @@ -483,6 +555,20 @@ def event( self, event ) :

return QtWidgets.QPlainTextEdit.event( self, event )

def resizeEvent ( self, event ) :

QtWidgets.QPlainTextEdit.resizeEvent( self, event )

contentsRect = self.contentsRect()
self.__lineNumberAreaWidget.setGeometry(
QtCore.QRect(
contentsRect.left(),
contentsRect.top(),
self.lineNumberAreaWidth(),
contentsRect.height()
)
)

def focusOutEvent( self, event ) :

widget = GafferUI.Widget._owner( self )
Expand Down Expand Up @@ -523,3 +609,18 @@ def __paintActivationHint( self, painter ) :
pixmap = GafferUI.Image._qtPixmapFromFile( "ctrlEnter.png" )
painter.setOpacity( 0.75 )
painter.drawPixmap( viewport.width() - ( pixmap.width() + 4 ), viewport.height() - ( pixmap.height() + 4 ), pixmap )

def __updateLineNumberAreaWidth( self, newBlockCount ) :

lineNumberAreaWidth = self.lineNumberAreaWidth()
self.setViewportMargins( lineNumberAreaWidth + ( 8 if lineNumberAreaWidth > 0 else 0 ), 0, 0, 0 )

def __updateLineNumberArea( self, rect, scrollY ) :

if scrollY != 0 :
self.__lineNumberAreaWidget.scroll( 0, scrollY )
else :
self.__lineNumberAreaWidget.update( 0, rect.y(), self.__lineNumberAreaWidget.width(), rect.height() )

if rect.contains( self.viewport().rect() ) :
self.__updateLineNumberAreaWidth( 0 )
2 changes: 1 addition & 1 deletion python/GafferUI/PythonEditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def __init__( self, scriptNode, **kw ) :
Gaffer.WeakMethod( self.__contextMenu )
)

self.__inputWidget = GafferUI.CodeWidget()
self.__inputWidget = GafferUI.CodeWidget( lineNumbers = True )

self.__splittable.append( self.__outputWidget )
self.__splittable.append( self.__inputWidget )
Expand Down
Loading