Skip to content
Merged
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

OpenCodeBlocks is an open-source tool for modular visual programing in python.

![](media/mnist_example.gif)

## Features

* Put your python code in small independent blocks
Expand Down
Binary file added media/mnist_example.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 48 additions & 4 deletions opencodeblocks/graphics/blocks/codeblock.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@

""" Module for the base OCB Code Block. """

import re
from typing import Optional

from PyQt5.QtCore import Qt, QByteArray, QPointF
from PyQt5.QtCore import QCoreApplication, Qt, QByteArray, QPointF
from PyQt5.QtGui import QPainter, QPainterPath, QPixmap
from PyQt5.QtWidgets import QStyleOptionGraphicsItem, QWidget, QGraphicsProxyWidget, QLabel, \
QGraphicsSceneMouseEvent, QApplication
QGraphicsSceneMouseEvent, QApplication, QPushButton

from opencodeblocks.graphics.blocks.block import OCBBlock
from opencodeblocks.graphics.pyeditor import PythonEditor

ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')

class OCBCodeBlock(OCBBlock):

"""
Expand All @@ -34,6 +37,7 @@ def __init__(self, **kwargs):

self.source_editor = self.init_source_editor()
self.display = self.init_display()
self.run_button = self.init_run_button()
self.stdout = ""
self.image = ""

Expand Down Expand Up @@ -75,6 +79,13 @@ def update_all(self):
int(self.width - 2*self.edge_size),
int(self.output_panel_height)
)
run_button_widget = self.run_button.widget()
run_button_widget.setGeometry(
int(self.edge_size),
int(self.edge_size + self.title_height),
int(2.5*self.edge_size),
int(2.5*self.edge_size)
)
super().update_all()

@property
Expand All @@ -100,7 +111,11 @@ def stdout(self, value:str):
# If there is a text output, erase the image output and display the text output
self.image = ""
editor_widget = self.display.widget()
editor_widget.setText(self._stdout)
# Remove ANSI color codes
text = ansi_escape.sub('', value)
# Remove backspaces (tf loading bars)
text = text.replace('\x08', '')
editor_widget.setText(text)

@property
def image(self) -> str:
Expand Down Expand Up @@ -171,7 +186,7 @@ def _stop_resize(self):
QApplication.restoreOverrideCursor()

def mouseMoveEvent(self, event:QGraphicsSceneMouseEvent):
"""
"""
We override the default resizing behavior as the code part and the display part of the block
block can be resized independently.
"""
Expand Down Expand Up @@ -206,3 +221,32 @@ def init_display(self):
display_graphics.setWidget(display)
display_graphics.setZValue(-1)
return display_graphics

def init_run_button(self):
""" Initialize the run button """
run_button_graphics = QGraphicsProxyWidget(self)
run_button = QPushButton(">")
run_button.setMinimumWidth(self.edge_size)
run_button_graphics.setWidget(run_button)
run_button.clicked.connect(self.run_code)
return run_button_graphics

def run_code(self):
"""Run the code in the block"""
code = self.source_editor.widget().text()
kernel = self.source_editor.widget().kernel
self.source = code
# Execute the code
kernel.client.execute(code)
done = False
# While the kernel sends messages
while done is False:
# Keep the GUI alive
QCoreApplication.processEvents()
# Save kernel message and display it
output, output_type, done = kernel.update_output()
if done is False:
if output_type == 'text':
self.stdout = output
elif output_type == 'image':
self.image = output
27 changes: 2 additions & 25 deletions opencodeblocks/graphics/pyeditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
""" Module for OCB in block python editor. """

from typing import TYPE_CHECKING, List
from PyQt5.QtCore import Qt, QCoreApplication
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFocusEvent, QFont, QFontMetrics, QColor
from PyQt5.Qsci import QsciScintilla, QsciLexerPython
from opencodeblocks.graphics.theme_manager import theme_manager
Expand All @@ -31,6 +31,7 @@ def __init__(self, block: OCBBlock):
"""
super().__init__(None)
self.block = block
self.kernel = kernel
self.setText(self.block.source)

self.update_theme()
Expand Down Expand Up @@ -101,28 +102,4 @@ def focusInEvent(self, event: QFocusEvent):
def focusOutEvent(self, event: QFocusEvent):
""" PythonEditor reaction to PyQt focusOut events. """
self.set_views_mode("MODE_NOOP")

code = self.text()
if self.isModified() and code != self.block.source:
self.block.source = code
self.setModified(False)
# Execute the code
kernel.client.execute(code)
done = False
# While the kernel sends messages
while done is False:
# Keep the GUI alive
QCoreApplication.processEvents()
# Save kernel message and display it
output, output_type, done = kernel.update_output()
if done is False:
if output_type == 'text':
self.block.stdout = output
elif output_type == 'image':
self.block.image = output
return super().focusOutEvent(event)

def gatherBlockInputs(self):
args = [2, 3]
kwargs = {"chicken": False}
return args, kwargs