├── .gitignore ├── .project ├── .pydevproject ├── .settings └── org.eclipse.core.resources.prefs ├── LICENSE ├── README.md ├── bin └── .gitignore ├── doc ├── screenshoot1.png ├── simbolbrowser.png ├── snipplets.png ├── terminal.png ├── toolbar.png └── toolbar.svg ├── freeze_setup.py ├── genexe.bat ├── mk_install.nsi ├── requeriments.txt ├── share └── uPyIDE │ ├── fakelibs │ └── pyb.py │ ├── help.css │ ├── help.html │ ├── help.md │ ├── images │ ├── about.png │ ├── document-new.png │ ├── document-open.png │ ├── document-save.png │ ├── download.png │ ├── run.png │ ├── splash.png │ ├── terminal-out.png │ ├── terminal.png │ ├── uPyIDE.ico │ ├── uPyIDE.png │ └── upload.png │ └── snipplet │ ├── Main_ExtInt.py │ ├── Main_PWM.py │ ├── Main_Timers.py │ ├── Main_Timers_2.py │ ├── Main_dac.py │ ├── Main_gc.py │ ├── Main_gpios.py │ ├── Main_perf.py │ ├── Main_perf2.py │ ├── Main_python.py │ ├── Main_rgb.py │ ├── Main_uart.py │ ├── Main_welcome.py │ ├── snipplet_class.py │ ├── snipplet_iterator.py │ ├── snipplet_main.py │ ├── snipplet_open.py │ ├── snipplet_try.py │ └── snipplets.xml ├── src ├── images │ ├── about.svg │ ├── document-new.svg │ ├── document-open.svg │ ├── document-save.svg │ ├── download.svg │ ├── run.svg │ ├── terminal-out.svg │ ├── terminal.svg │ └── upload.svg ├── myDef.py ├── pyqode_i18n.py ├── server.py ├── termWidget.py └── uPyIDE.py └── svg2png.bat /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | target/ 60 | 61 | *.exe 62 | /*.nja 63 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | uPyEDU-CIAA 4 | 5 | 6 | 7 | 8 | 9 | org.python.pydev.PyDevBuilder 10 | 11 | 12 | 13 | 14 | 15 | org.python.pydev.pythonNature 16 | 17 | 18 | -------------------------------------------------------------------------------- /.pydevproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | /${PROJECT_DIR_NAME}/src 5 | 6 | python 3.0 7 | Default 8 | 9 | /usr/local/lib/python3.4/dist-packages/pyqode/qt 10 | /usr/local/lib/python3.4/dist-packages/pyqode/core 11 | /usr/local/lib/python3.4/dist-packages/pyqode/python 12 | 13 | 14 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/resources.py=utf-8 3 | encoding//src/server.py=utf-8 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # uPython IDE 2 | 3 | This is the IDE for micropython on EDU-CIAA. 4 | 5 | #### Requeriments 6 | 7 | - Python 3.X 8 | - PyQt or PySide 9 | - PyQode 10 | - PySerial 11 | - PyTE 12 | - tendo 13 | 14 | #### Requeriment instalation 15 | 16 | On ubuntu and derivates, this require python3, cmake, qt4-qmake, libqt4-core 17 | and libqt4-gui installed into the system. You can install all with: 18 | 19 | ```bash 20 | sudo apt-get install python3 cmake qt4-qmake libqt4-core libqt4-gui 21 | ``` 22 | 23 | ```bash 24 | pip install pyside pyqode.python pyserial pyte tendo 25 | ``` 26 | 27 | Replace pip by pip3 or command of your distribution. 28 | 29 | In Ubuntu, PySide can fail to compile. At this case you can use PyQt4 and 30 | others packages from official repositories 31 | 32 | ```bash 33 | sudo apt-get install python3 python3-qt4 34 | sudo pip3 install pyserial tendo pyte pyqode.python markdown 35 | ``` 36 | 37 | ### Characteristics 38 | 39 | - Syntax higlight 40 | - Autocomplete 41 | - Online help 42 | - Parameter lints 43 | - PEP8 code style lints 44 | - Simbol browser 45 | - Code Snipplets 46 | - Embedded serial terminal 47 | 48 | ### Usage 49 | 50 | This is the main window 51 | ![Main Window](doc/screenshoot1.png) 52 | 53 | #### Tool Bar 54 | ![Toolbar](doc/toolbar.png) 55 | 56 | Actions: 57 | - **New**: Clear context of editor 58 | - **Open**: Open file on editor 59 | - **Save**: Save current editor context. 60 | - **Run**: Execute script directly into board 61 | - **Download**: Save script into board 62 | - **Show Terminal**: Switch to terminal view 63 | 64 | #### Side Views 65 | 66 | ###### Symbol bar 67 | This view allows quick access to the symbols in the code on editor 68 | 69 | ![Toolbar](doc/simbolbrowser.png) 70 | 71 | ###### Snipplets 72 | This view show some code snipplets to speed edition 73 | 74 | ![Toolbar](doc/snipplets.png) 75 | 76 | #### Terminal 77 | 78 | ![Terminal](doc/terminal.png) 79 | -------------------------------------------------------------------------------- /bin/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /doc/screenshoot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/doc/screenshoot1.png -------------------------------------------------------------------------------- /doc/simbolbrowser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/doc/simbolbrowser.png -------------------------------------------------------------------------------- /doc/snipplets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/doc/snipplets.png -------------------------------------------------------------------------------- /doc/terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/doc/terminal.png -------------------------------------------------------------------------------- /doc/toolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/doc/toolbar.png -------------------------------------------------------------------------------- /doc/toolbar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 24 | 32 | 36 | 37 | 38 | 60 | 62 | 63 | 65 | image/svg+xml 66 | 68 | 69 | 70 | 71 | 72 | 77 | 85 | 92 | New 103 | Save 114 | Open 125 | Run 136 | Download 147 | Show Terminal 158 | 164 | 170 | 176 | 182 | 188 | Port selection 199 | 200 | 201 | -------------------------------------------------------------------------------- /freeze_setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | This setup script build a frozen distribution of the application (with the 5 | python interpreter and 3rd party libraries embedded) for Windows. 6 | 7 | Run the following command to freeze the app (the frozen executable can be 8 | found in the bin folder:: 9 | 10 | python freeze_setup.py build 11 | 12 | """ 13 | import os 14 | import sys 15 | from cx_Freeze import setup, Executable 16 | import shutil 17 | from pyqode.core.api.syntax_highlighter import get_all_styles 18 | from pyqode.python.backend import server 19 | 20 | # from src.uPyIDE import __version__ 21 | 22 | sys.path.append(os.path.join(os.path.dirname(__file__), 'src')) 23 | import uPyIDE 24 | 25 | # automatically build when run without arguments 26 | if len(sys.argv) == 1: 27 | sys.argv.append("build") 28 | 29 | # collect pygments styles 30 | pygments_styles = [] 31 | for s in get_all_styles(): 32 | module = 'pygments.styles.%s' % s.replace('-', '_') 33 | try: 34 | __import__(module) 35 | except ImportError: 36 | pass 37 | else: 38 | pygments_styles.append(module) 39 | print('pygment styles', pygments_styles) 40 | 41 | 42 | # Build options 43 | options = { 44 | "excludes": ["PyQt5.uic.port_v3", "tcltk", "jedi"], 45 | "namespace_packages": ["pyqode"], 46 | "include_msvcr": True, 47 | "build_exe": "bin", 48 | "includes": ["pkg_resources", "PySide.QtCore", 'PySide.QtGui', 49 | 'PySide.QtNetwork', 'pydoc'] + pygments_styles 50 | } 51 | 52 | 53 | # Run the cxFreeze setup 54 | setup(name="uPyIDE", 55 | version='1.0', #__version__, 56 | options={"build_exe": options}, 57 | executables=[ 58 | Executable(uPyIDE.__file__.replace('.pyc', '.py'), 59 | targetName="uPyIDE.exe", 60 | packages='uPyIDE', 61 | icon='share/uPyIDE/images/uPyIDE.ico', 62 | base="Win32GUI"), 63 | Executable(server.__file__.replace('.pyc', '.py'), 64 | targetName="server.exe")]) 65 | 66 | 67 | # NOTE: if you are using PyQt5, you will have to copy libEGL.dll manually 68 | try: 69 | import PyQt5 70 | except ImportError: 71 | pass # pyqt4 or pyqside 72 | else: 73 | shutil.copy(os.path.join(os.path.dirname(PyQt5.__file__), 'libEGL.dll'), 'bin') 74 | 75 | 76 | # cx_freeze has some issues embedding the jedi package, let's do it ourself 77 | import jedi 78 | try: 79 | shutil.copytree(os.path.dirname(jedi.__file__), 'bin/jedi') 80 | except OSError: 81 | pass 82 | 83 | # also copy server.py in order to be able to run on external interpreters 84 | shutil.copy(server.__file__, 'bin') 85 | -------------------------------------------------------------------------------- /genexe.bat: -------------------------------------------------------------------------------- 1 | \Python34\Scripts\pyinstaller.exe -w -F --distpath=bin -i share\uPyIDE\images\uPyIDE.ico src\uPyIDE.py 2 | \Python34\Scripts\pyinstaller.exe -w -F --distpath=bin -i share\uPyIDE\images\uPyIDE.ico src\server.py 3 | -------------------------------------------------------------------------------- /mk_install.nsi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/mk_install.nsi -------------------------------------------------------------------------------- /requeriments.txt: -------------------------------------------------------------------------------- 1 | PySide 2 | pyqode.python 3 | pyserial 4 | pyte 5 | tendo -------------------------------------------------------------------------------- /share/uPyIDE/fakelibs/pyb.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Created on 28 de ago. de 2016 3 | 4 | @author: martin 5 | ''' 6 | 7 | 8 | def delay(milis): 9 | pass 10 | 11 | 12 | class LED: 13 | def __init__(self, led_id): 14 | pass 15 | 16 | def intensity(self, value=0): 17 | pass 18 | 19 | def on(self): 20 | pass 21 | 22 | def off(self): 23 | pass 24 | 25 | def toggle(self): 26 | pass 27 | 28 | 29 | class Switch: 30 | def __init__(self, switch_id): 31 | pass 32 | 33 | def __call__(self): 34 | pass 35 | 36 | def callback(self, func): 37 | pass 38 | 39 | 40 | class UART: 41 | RTS = None 42 | CTS = None 43 | 44 | def __init__(self, uart_id): 45 | pass 46 | 47 | def init(self, baud=115200, bits=8, parity=None, stop=1, timeout=1000, 48 | timeout_char=1000, read_buf_len=64, packet=False): 49 | pass 50 | 51 | def deinit(self): 52 | pass 53 | 54 | def read(self, nbytes=None): 55 | pass 56 | 57 | def readall(self): 58 | pass 59 | 60 | def readline(self): 61 | pass 62 | 63 | def readinto(self, buffer, nbytes=None): 64 | pass 65 | 66 | def any(self): 67 | pass 68 | 69 | def write(self, data): 70 | pass 71 | 72 | def readchar(self): 73 | pass 74 | 75 | def writechar(self): 76 | pass 77 | 78 | def sendbreack(self): 79 | pass 80 | 81 | 82 | class Pin: 83 | IN = None 84 | OUT_PP = None 85 | OUT_OD = None 86 | AF_PP = None 87 | AF_OD = None 88 | ANALOG = None 89 | 90 | PULL_NONE = None 91 | PULL_UP = None 92 | PULL_DOWN = None 93 | 94 | def __init__(self, pin_id): 95 | pass 96 | 97 | def init(self, mode, pull=PULL_NONE, af=-1): 98 | pass 99 | 100 | def value(self, value=None): 101 | pass 102 | 103 | def __str__(self): 104 | pass 105 | 106 | def af(self): 107 | pass 108 | 109 | def gpio(self): 110 | pass 111 | 112 | def mode(self): 113 | pass 114 | 115 | def name(self): 116 | pass 117 | 118 | def names(self): 119 | pass 120 | 121 | def pin(self): 122 | pass 123 | 124 | def port(self): 125 | pass 126 | 127 | def pull(self): 128 | pass 129 | 130 | 131 | class ExtInt: 132 | IRQ_FALLING = None 133 | IRQ_RISING = None 134 | IRQ_RISING_FALLING = None 135 | 136 | def __init__(self, pin, mode, pull, callback): 137 | pass 138 | 139 | def enable(self): 140 | pass 141 | 142 | def disable(self): 143 | pass 144 | 145 | def swint(self): 146 | pass 147 | 148 | 149 | class DAC: 150 | NORMAL = None 151 | CIRCULAR = None 152 | 153 | def __init__(self, dac_line, bits=10): 154 | pass 155 | 156 | def init(self, bits=10): 157 | pass 158 | 159 | def noise(self): 160 | pass 161 | 162 | def triangle(self): 163 | pass 164 | 165 | def write(self, value): 166 | pass 167 | 168 | def write_timed(self, data, frec, *, mode=DAC_NORMAL): 169 | pass 170 | 171 | 172 | class Timer: 173 | def __init__(self, timer_id): 174 | pass 175 | 176 | def init(self, *, frec, prescaler, period): 177 | pass 178 | 179 | def deinit(self): 180 | pass 181 | 182 | def callback(self, fun): 183 | pass 184 | 185 | def interval(self, period, func): 186 | pass 187 | 188 | def timeout(self, period, func): 189 | pass 190 | 191 | def counter(self, value=None): 192 | pass 193 | 194 | def freq(self, value=None): 195 | pass 196 | 197 | def period(self, value=None): 198 | pass 199 | 200 | def prescaler(self, value=None): 201 | pass 202 | 203 | def source_freq(self, value=None): 204 | pass 205 | 206 | 207 | class PWM: 208 | @staticmethod 209 | def set_frecuency(frec): 210 | pass 211 | 212 | def __init__(self, channel): 213 | pass 214 | 215 | def duty_cycle(self, duty): 216 | pass 217 | 218 | 219 | class ADC: 220 | def __init__(self, channel): 221 | pass 222 | 223 | def read(self): 224 | pass 225 | 226 | 227 | class EEPROM: 228 | def __init__(self): 229 | pass 230 | 231 | def read_byte(self): 232 | pass 233 | 234 | def read_int(self): 235 | pass 236 | 237 | def read_float(self): 238 | pass 239 | 240 | def write_byte(self, val): 241 | pass 242 | 243 | def write_int(self, val): 244 | pass 245 | 246 | def write_float(self, val): 247 | pass 248 | 249 | def write(self, val): 250 | pass 251 | 252 | def readall(self): 253 | pass 254 | 255 | 256 | class SPI: 257 | def __init__(self, bits, mode, bitrate): 258 | pass 259 | 260 | def write(self, data, length): 261 | pass 262 | 263 | def read(self, length): 264 | pass 265 | 266 | def readinto(self, buffer): 267 | pass 268 | 269 | def write_read_into(self, wbuff, rbuff): 270 | pass 271 | 272 | 273 | class RTC: 274 | MASK_SEC = 1 << 0 275 | MASK_MIN = 1 << 1 276 | MASK_HR = 1 << 2 277 | MASK_DAY = 1 << 3 278 | MASK_MON = 1 << 4 279 | MASK_YR = 1 << 6 280 | MASK_DOW = 1 << 7 281 | 282 | def __init__(self): 283 | pass 284 | 285 | def datetime(self, dt_tuple=None): 286 | pass 287 | 288 | def alarm_datetime(self, dt_tuple=None, alarmMask=None): 289 | pass 290 | 291 | def alarm_disable(self): 292 | pass 293 | 294 | def callback(self, functor): 295 | pass 296 | 297 | def read_bkp_reg(self, addr): 298 | pass 299 | 300 | def write_bkp_reg(self, addr, value): 301 | pass 302 | 303 | def calibration(self, value): 304 | pass 305 | 306 | 307 | class I2C: 308 | def __init__(self, frec): 309 | pass 310 | 311 | def write(self, data, length): 312 | pass 313 | 314 | def read(self, length): 315 | pass 316 | 317 | def readinto(self, buffer): 318 | pass 319 | 320 | def slave_addr(self, addr=None): 321 | pass 322 | 323 | -------------------------------------------------------------------------------- /share/uPyIDE/help.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | color: blue; 3 | } 4 | -------------------------------------------------------------------------------- /share/uPyIDE/help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

uPyIDE Help

4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /share/uPyIDE/help.md: -------------------------------------------------------------------------------- 1 | *** uPyIDE *** 2 | 3 | - TODO -------------------------------------------------------------------------------- /share/uPyIDE/images/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/share/uPyIDE/images/about.png -------------------------------------------------------------------------------- /share/uPyIDE/images/document-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/share/uPyIDE/images/document-new.png -------------------------------------------------------------------------------- /share/uPyIDE/images/document-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/share/uPyIDE/images/document-open.png -------------------------------------------------------------------------------- /share/uPyIDE/images/document-save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/share/uPyIDE/images/document-save.png -------------------------------------------------------------------------------- /share/uPyIDE/images/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/share/uPyIDE/images/download.png -------------------------------------------------------------------------------- /share/uPyIDE/images/run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/share/uPyIDE/images/run.png -------------------------------------------------------------------------------- /share/uPyIDE/images/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/share/uPyIDE/images/splash.png -------------------------------------------------------------------------------- /share/uPyIDE/images/terminal-out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/share/uPyIDE/images/terminal-out.png -------------------------------------------------------------------------------- /share/uPyIDE/images/terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/share/uPyIDE/images/terminal.png -------------------------------------------------------------------------------- /share/uPyIDE/images/uPyIDE.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/share/uPyIDE/images/uPyIDE.ico -------------------------------------------------------------------------------- /share/uPyIDE/images/uPyIDE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/share/uPyIDE/images/uPyIDE.png -------------------------------------------------------------------------------- /share/uPyIDE/images/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martinribelotta/uPyIDE/5d2cd5201a541d7e7e373ead46c8f77add7bf471/share/uPyIDE/images/upload.png -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/Main_ExtInt.py: -------------------------------------------------------------------------------- 1 | # Description ADC Test 2 | import pyb 3 | 4 | 5 | def callBack(line): 6 | print("Pin Interrupt!") 7 | print("Line =", line) 8 | 9 | p = pyb.Pin(0) 10 | p.init(pyb.Pin.OUT_PP, pyb.Pin.PULL_NONE) 11 | print(p) 12 | intr = pyb.ExtInt(p, pyb.ExtInt.IRQ_RISING, pyb.Pin.PULL_NONE, callBack) 13 | print(intr) 14 | 15 | intr.disable() 16 | intr.enable() 17 | 18 | switch1 = pyb.Switch(1) 19 | 20 | while True: 21 | pyb.delay(1000) 22 | print("tick") 23 | if switch1.switch(): 24 | int.swint() 25 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/Main_PWM.py: -------------------------------------------------------------------------------- 1 | import pyb 2 | 3 | print("Test PWM") 4 | 5 | print("Setting frequency...") 6 | pyb.PWM.set_frequency(1000) 7 | 8 | print("Creating pwm for out0") 9 | out0 = pyb.PWM(0) 10 | 11 | print("Setting duty cycle to 50%") 12 | out0.duty_cycle(50) 13 | print("Duty cycle :"+str(out0.duty_cycle())) 14 | 15 | out1= pyb.PWM(1) 16 | out1.duty_cycle(25) 17 | 18 | out10= pyb.PWM(10) 19 | out10.duty_cycle(75) 20 | 21 | 22 | print("Main loop") 23 | while True: 24 | pyb.delay(100) 25 | 26 | 27 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/Main_Timers.py: -------------------------------------------------------------------------------- 1 | import pyb 2 | import math 3 | 4 | def callb(timer): 5 | print("Timer tick") 6 | print(timer) 7 | 8 | 9 | print("Test Timers") 10 | 11 | 12 | t2 = pyb.Timer(2) 13 | 14 | print(t2) 15 | 16 | t2.init(freq=1) 17 | t2.callback(callb) 18 | 19 | 20 | while True: 21 | pyb.delay(1000) 22 | 23 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/Main_Timers_2.py: -------------------------------------------------------------------------------- 1 | import pyb 2 | 3 | def callb(timer): 4 | print("Interval interrupt") 5 | print(timer) 6 | 7 | def callbTimeout (timer): 8 | print("Timeout interrupt") 9 | print(timer) 10 | 11 | print("Test Timers") 12 | 13 | t1 = pyb.Timer(1) 14 | t2 = pyb.Timer(2) 15 | 16 | t1.interval(2000,callb) 17 | t2.timeout(5000,callbTimeout) 18 | 19 | t1.freq(1) 20 | print("f t1:"+str(t1.freq())) 21 | 22 | t1.period(204000000) 23 | t1.prescaler(3) 24 | print("period t1:"+str(t1.period())) 25 | print("presc t1:"+str(t1.prescaler())) 26 | 27 | t1.counter(0) 28 | print("counter t1:"+str(t1.counter())) 29 | 30 | print("src freq t1:"+str(t1.source_freq())) 31 | 32 | 33 | while True: 34 | pyb.delay(100) 35 | 36 | #t1.counter(0) 37 | #t1.deinit() 38 | 39 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/Main_dac.py: -------------------------------------------------------------------------------- 1 | # Description: ADC test 2 | import pyb 3 | import math 4 | 5 | print("Test DAC") 6 | 7 | dac = pyb.DAC(1) 8 | 9 | print(dac) 10 | 11 | #dac.triangle(5000) 12 | #dac.noise(5000) 13 | 14 | # sawtooth 15 | #buf = bytearray(200) 16 | #j=0 17 | #for i in range (0,len(buf)/2): 18 | # v = int(i*10) 19 | # buf[j+1] = (v >> 8) & 0xff 20 | # buf[j] = v & 0xff 21 | # j=j+2 22 | 23 | # sine 24 | buf = bytearray(200) 25 | j=0 26 | for i in range (0,len(buf)/2): 27 | v = 512 + int(511 * math.sin(2 * math.pi * i / (len(buf)/2) ) ) 28 | buf[j+1] = (v >> 8) & 0xff 29 | buf[j] = v & 0xff 30 | j=j+2 31 | 32 | # output the sine-wave at 400Hz 33 | print("sine created") 34 | 35 | dac.write_timed(buf, 400*(int(len(buf)/2)), mode=pyb.DAC.CIRCULAR) 36 | 37 | 38 | while True: 39 | print("tick") 40 | pyb.delay(1000) 41 | #dac.write(0) 42 | pyb.delay(1000) 43 | #dac.write(512) 44 | pyb.delay(1000) 45 | #dac.write(1013) 46 | 47 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/Main_gc.py: -------------------------------------------------------------------------------- 1 | # Description: Garbage collection test 2 | import pyb 3 | import math 4 | 5 | class Clase: 6 | def __init__(self): 7 | pass 8 | 9 | def miMetodo(self,arg): 10 | print("Mi metodo:"+str(arg)) 11 | 12 | c = Clase() 13 | 14 | led1 = pyb.LED(1) 15 | led2 = pyb.LED(2) 16 | led3 = pyb.LED(3) 17 | 18 | switch1 = pyb.Switch(1) 19 | switch2 = pyb.Switch(2) 20 | switch3 = pyb.Switch(3) 21 | switch4 = pyb.Switch(4) 22 | 23 | counter=0 24 | while(True): 25 | print('Estado de pulsadores:') 26 | val = switch1.value() 27 | print('sw1 vale:'+str(val)) 28 | val = switch2.value() 29 | print('sw2 vale:'+str(val)) 30 | val = switch3.value() 31 | print('sw3 vale:'+str(val)) 32 | val = switch4.value() 33 | print('sw4 vale:'+str(val)) 34 | 35 | counter=counter+1 36 | print('Modificacion de leds:'+str(counter)) 37 | print('Enciendo') 38 | led1.on() 39 | pyb.delay(100); 40 | print('Apago') 41 | led1.off() 42 | pyb.delay(100); 43 | 44 | #print('Enciendo') 45 | #led2.on() 46 | #pyb.delay(1000); 47 | #print('Apago') 48 | #led2.off() 49 | #pyb.delay(1000); 50 | 51 | #print('Enciendo') 52 | #led3.on() 53 | #pyb.delay(1000); 54 | #print('Apago') 55 | #led3.off() 56 | #pyb.delay(1000); 57 | 58 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/Main_gpios.py: -------------------------------------------------------------------------------- 1 | import pyb 2 | 3 | p = pyb.Pin(8) 4 | p.init(pyb.Pin.OUT_PP,pyb.Pin.PULL_NONE) 5 | print(p) 6 | 7 | while True: 8 | #p.value(True) 9 | p.high() 10 | print("value:"+str(p.value())) 11 | 12 | pyb.delay(1000) 13 | 14 | #p.value(False) 15 | p.low() 16 | print("value:"+str(p.value())) 17 | 18 | pyb.delay(1000) 19 | 20 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/Main_perf.py: -------------------------------------------------------------------------------- 1 | import pyb 2 | 3 | @micropython.native 4 | def performanceTest(): 5 | d = 10000 6 | print("start. Wait for %d milis" % d) 7 | millis = pyb.millis 8 | endTime = millis() + d 9 | count = 0 10 | while millis() < endTime: 11 | count += 1 12 | print("Count: ", count) 13 | 14 | while(True): 15 | performanceTest() 16 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/Main_perf2.py: -------------------------------------------------------------------------------- 1 | import pyb 2 | 3 | led1 = pyb.LED(1) 4 | led2 = pyb.LED(2) 5 | led3 = pyb.LED(3) 6 | 7 | #@micropython.native 8 | def speed(): 9 | for i in range(1000000): 10 | led1.on() 11 | led1.off() 12 | 13 | 14 | speed() 15 | 16 | 17 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/Main_python.py: -------------------------------------------------------------------------------- 1 | import math 2 | import collections 3 | 4 | class Clase: 5 | def __init__(self): 6 | pass 7 | 8 | def miMetodo(self,arg): 9 | print("Mi metodo:"+str(arg)) 10 | 11 | #Test class 12 | c = Clase() 13 | c.miMetodo(56) 14 | 15 | # Test bytearray 16 | ba = bytearray() 17 | ba.append(33) 18 | 19 | # Test slice 20 | values = [100, 200, 300, 400, 500] 21 | slice = values[2:-1] 22 | print(slice) 23 | values = "Hello World" 24 | evens = values[:2] 25 | print(evens) 26 | 27 | # Test math 28 | s = math.sqrt(2) 29 | print("sqrt(2)="+str(s)) 30 | 31 | # Test array 32 | from array import * 33 | x=array('f',[0.0,1.0,2.0]) 34 | print(x) 35 | 36 | # Test Set 37 | print("Test de Sets") 38 | x = [1, 1, 2, 2, 2, 2, 2, 3, 3] 39 | s = set(x) 40 | print(s) 41 | 42 | #Test tuples 43 | a,b = 4,6 44 | print("a:"+str(a)+" b:"+str(b)) 45 | a,b,c = 4,5,6 46 | print("a:"+str(a)+" b:"+str(b)+" c:"+str(c)) 47 | 48 | #Test collection 49 | Person = collections.namedtuple("Person", ["name", "age", "gender"] ) 50 | bob = Person(name='Bob', age=30, gender='male') 51 | print(bob) 52 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/Main_rgb.py: -------------------------------------------------------------------------------- 1 | import pyb 2 | import math 3 | 4 | print("Test led RGB") 5 | 6 | 7 | ledR = pyb.LED(4) 8 | ledG = pyb.LED(5) 9 | ledB = pyb.LED(6) 10 | 11 | s0 = bytearray(100) 12 | for i in range (0,len(s0)): 13 | s0[i] = 8 + int(7 * math.sin(2 * math.pi * i / (len(s0)) ) ) 14 | 15 | s1 = bytearray(100) 16 | for i in range (0,len(s1)): 17 | s1[i] = 8 + int(7 * math.sin( (1/3)*math.pi + 2 * math.pi * i / (len(s1)) ) ) 18 | 19 | s2 = bytearray(100) 20 | for i in range (0,len(s2)): 21 | s2[i] = 8 + int(7 * math.sin( (2/3)*math.pi + 2 * math.pi * i / (len(s2)) ) ) 22 | 23 | t=0 24 | while True: 25 | pyb.delay(30) 26 | val = s0[t] 27 | ledR.intensity(val) 28 | #print("intensity:"+str(ledR.intensity())) 29 | 30 | val=s1[t] 31 | ledG.intensity(val) 32 | 33 | val=s2[t] 34 | ledB.intensity(val) 35 | 36 | t+=1 37 | if t==100: 38 | t=0 39 | 40 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/Main_uart.py: -------------------------------------------------------------------------------- 1 | import pyb 2 | 3 | uart = pyb.UART(0) 4 | 5 | #uart.init(115200,bits=8, parity=None, stop=1,timeout=0, timeout_char=1000, read_buf_len=64,packet_mode=True,packet_end_char=ord('o')) 6 | uart.init(115200,bits=8, parity=None, stop=1,timeout=1000, timeout_char=1000, read_buf_len=64) 7 | #uart.init(115200) 8 | 9 | print(uart) 10 | 11 | while True: 12 | uart.write("A") 13 | pyb.delay(1000) 14 | if uart.any(): 15 | print("hay data:") 16 | 17 | # Test 1 18 | #d = uart.readchar() 19 | #print(str(d)) 20 | #uart.writechar(d) 21 | 22 | #Test 2 23 | #data = uart.read() 24 | data = uart.readall() 25 | #data = uart.readline() 26 | #data = uart.read(3) 27 | 28 | #buf = bytearray(256) 29 | #bytes = uart.readinto(buf) 30 | #if bytes != 0: 31 | # print(buf) 32 | 33 | print(data) 34 | uart.write(data) 35 | 36 | uart.deinit() 37 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/Main_welcome.py: -------------------------------------------------------------------------------- 1 | print("Welcome to Micropython on EDU-CIAA-NXP") 2 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/snipplet_class.py: -------------------------------------------------------------------------------- 1 | # Description: Class declaration 2 | class NAME(object): 3 | def __init__(self): 4 | pass 5 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/snipplet_iterator.py: -------------------------------------------------------------------------------- 1 | # Description: Object iterator 2 | class firstn(object): 3 | def __init__(self, n): 4 | self.n = n 5 | self.num = 0 6 | 7 | def __iter__(self): 8 | return self 9 | 10 | # Python 3 compatibility 11 | def __next__(self): 12 | return self.next() 13 | 14 | def next(self): 15 | if self.num < self.n: 16 | cur, self.num = self.num, self.num+1 17 | return cur 18 | else: 19 | raise StopIteration() 20 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/snipplet_main.py: -------------------------------------------------------------------------------- 1 | # Description: Main of module 2 | if __name__ == '__main__': 3 | pass 4 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/snipplet_open.py: -------------------------------------------------------------------------------- 1 | # Description: open file 2 | with open('NAME', 'rwa+') as f: 3 | pass 4 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/snipplet_try.py: -------------------------------------------------------------------------------- 1 | # Description: Try/Except/Finally/Else block 2 | try: 3 | pass 4 | except Exception as e: 5 | print(e) 6 | else: 7 | pass 8 | finally: 9 | pass 10 | -------------------------------------------------------------------------------- /share/uPyIDE/snipplet/snipplets.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 15 | 16 | 32 | 33 | 48 | 49 | -------------------------------------------------------------------------------- /src/images/about.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 31 | 34 | 38 | 42 | 43 | 53 | 56 | 60 | 64 | 65 | 74 | 76 | 80 | 84 | 85 | 87 | 91 | 95 | 96 | 106 | 115 | 117 | 121 | 125 | 126 | 135 | 144 | 146 | 150 | 154 | 155 | 164 | 166 | 170 | 174 | 175 | 177 | 181 | 185 | 186 | 196 | 198 | 202 | 206 | 207 | 217 | 226 | 236 | 239 | 243 | 247 | 248 | 258 | 261 | 265 | 269 | 270 | 279 | 281 | 285 | 289 | 290 | 292 | 296 | 300 | 301 | 311 | 320 | 322 | 326 | 330 | 331 | 340 | 349 | 351 | 355 | 359 | 360 | 369 | 371 | 375 | 379 | 380 | 382 | 386 | 390 | 391 | 401 | 410 | 411 | 444 | 446 | 447 | 449 | image/svg+xml 450 | 452 | 453 | 454 | 455 | 456 | 461 | 464 | 467 | 468 | 471 | 480 | 485 | ? 497 | 498 | 499 | 500 | -------------------------------------------------------------------------------- /src/images/document-new.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 22 | 24 | 28 | 32 | 33 | 35 | 39 | 43 | 44 | 54 | 64 | 73 | 75 | 79 | 83 | 84 | 93 | 102 | 104 | 108 | 112 | 113 | 122 | 132 | 134 | 138 | 142 | 143 | 145 | 149 | 153 | 154 | 163 | 166 | 170 | 174 | 175 | 185 | 188 | 192 | 196 | 197 | 207 | 217 | 227 | 228 | 257 | 264 | 268 | 272 | 276 | 280 | 284 | 288 | 292 | 296 | 300 | 304 | 308 | 312 | 316 | 320 | 324 | 328 | 332 | 336 | 340 | 344 | 348 | 352 | 356 | 360 | 361 | 363 | 364 | 366 | image/svg+xml 367 | 369 | 370 | 371 | 372 | 373 | 378 | 387 | 393 | 398 | 401 | 406 | 409 | 414 | 419 | 420 | 421 | 422 | 423 | -------------------------------------------------------------------------------- /src/images/document-open.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 22 | 24 | 28 | 32 | 33 | 35 | 39 | 43 | 44 | 54 | 64 | 73 | 75 | 79 | 83 | 84 | 93 | 102 | 104 | 108 | 112 | 113 | 122 | 132 | 134 | 138 | 142 | 143 | 144 | 173 | 176 | 180 | 184 | 188 | 192 | 196 | 200 | 204 | 208 | 212 | 216 | 220 | 224 | 228 | 232 | 236 | 240 | 244 | 248 | 252 | 256 | 260 | 264 | 268 | 272 | 273 | 275 | 276 | 278 | image/svg+xml 279 | 281 | 282 | 283 | 284 | 285 | 290 | 299 | 305 | 310 | 313 | 320 | 327 | 332 | 333 | 334 | 335 | -------------------------------------------------------------------------------- /src/images/document-save.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 22 | 24 | 28 | 32 | 33 | 35 | 39 | 43 | 44 | 54 | 64 | 73 | 75 | 79 | 83 | 84 | 93 | 102 | 104 | 108 | 112 | 113 | 122 | 132 | 134 | 138 | 142 | 143 | 152 | 154 | 158 | 162 | 163 | 164 | 193 | 196 | 200 | 204 | 208 | 212 | 216 | 220 | 224 | 228 | 232 | 236 | 240 | 244 | 248 | 252 | 256 | 260 | 264 | 268 | 272 | 276 | 280 | 284 | 288 | 292 | 293 | 295 | 296 | 298 | image/svg+xml 299 | 301 | 302 | 303 | 304 | 305 | 310 | 319 | 325 | 330 | 333 | 339 | 345 | 353 | 361 | 366 | 367 | 368 | 369 | -------------------------------------------------------------------------------- /src/images/download.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 22 | 24 | 28 | 32 | 33 | 35 | 39 | 43 | 44 | 54 | 64 | 73 | 75 | 79 | 83 | 84 | 93 | 102 | 104 | 108 | 112 | 113 | 122 | 123 | 149 | 152 | 156 | 160 | 164 | 168 | 172 | 176 | 180 | 184 | 188 | 192 | 196 | 200 | 204 | 208 | 212 | 216 | 220 | 224 | 228 | 232 | 236 | 240 | 244 | 248 | 249 | 251 | 252 | 254 | image/svg+xml 255 | 257 | 258 | 259 | 260 | 261 | 266 | 275 | 281 | 286 | 288 | 294 | 300 | 301 | 302 | 303 | -------------------------------------------------------------------------------- /src/images/run.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 22 | 24 | 28 | 32 | 33 | 35 | 39 | 43 | 44 | 54 | 64 | 73 | 75 | 79 | 83 | 84 | 93 | 102 | 104 | 108 | 112 | 113 | 122 | 123 | 150 | 153 | 157 | 161 | 165 | 169 | 173 | 177 | 181 | 185 | 189 | 193 | 197 | 201 | 205 | 209 | 213 | 217 | 221 | 225 | 229 | 233 | 237 | 241 | 245 | 249 | 250 | 252 | 253 | 255 | image/svg+xml 256 | 258 | 259 | 260 | 261 | 262 | 267 | 276 | 282 | 287 | 290 | 296 | 297 | 298 | 299 | -------------------------------------------------------------------------------- /src/images/terminal-out.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 29 | 34 | 35 | 37 | 41 | 45 | 46 | 48 | 52 | 56 | 57 | 59 | 63 | 67 | 68 | 77 | 86 | 95 | 105 | 115 | 125 | 135 | 144 | 146 | 150 | 154 | 155 | 164 | 174 | 184 | 194 | 195 | 227 | 230 | 234 | 238 | 242 | 246 | 250 | 254 | 258 | 262 | 266 | 270 | 274 | 278 | 282 | 286 | 290 | 294 | 298 | 302 | 306 | 310 | 311 | 313 | 314 | 316 | image/svg+xml 317 | 319 | 320 | 321 | 322 | 323 | 328 | 335 | 341 | 346 | 353 | 358 | 363 | 371 | 379 | 382 | 387 | 395 | 396 | 397 | 398 | -------------------------------------------------------------------------------- /src/images/terminal.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 29 | 34 | 35 | 37 | 41 | 45 | 46 | 48 | 52 | 56 | 57 | 59 | 63 | 67 | 68 | 77 | 86 | 95 | 105 | 115 | 125 | 135 | 144 | 146 | 150 | 154 | 155 | 164 | 174 | 184 | 194 | 195 | 227 | 230 | 234 | 238 | 242 | 246 | 250 | 254 | 258 | 262 | 266 | 270 | 274 | 278 | 282 | 286 | 290 | 294 | 298 | 302 | 306 | 310 | 311 | 313 | 314 | 316 | image/svg+xml 317 | 319 | 320 | 321 | 322 | 323 | 328 | 335 | 341 | 346 | 353 | 358 | 363 | 371 | 379 | 381 | 386 | 394 | 395 | 396 | 397 | -------------------------------------------------------------------------------- /src/images/upload.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 22 | 24 | 28 | 32 | 33 | 35 | 39 | 43 | 44 | 54 | 64 | 73 | 75 | 79 | 83 | 84 | 93 | 102 | 104 | 108 | 112 | 113 | 122 | 123 | 149 | 152 | 156 | 160 | 164 | 168 | 172 | 176 | 180 | 184 | 188 | 192 | 196 | 200 | 204 | 208 | 212 | 216 | 220 | 224 | 228 | 232 | 236 | 240 | 244 | 248 | 249 | 251 | 252 | 254 | image/svg+xml 255 | 257 | 258 | 259 | 260 | 261 | 266 | 275 | 281 | 286 | 292 | 298 | 299 | 300 | -------------------------------------------------------------------------------- /src/myDef.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Tue Jul 25 00:22:16 2017 5 | 6 | @author: coolshou 7 | """ 8 | import pyqode_i18n 9 | import locale 10 | 11 | def i18n(s): 12 | lang, encode = locale.getdefaultlocale() 13 | return pyqode_i18n.tr(s, lang=lang) 14 | 15 | -------------------------------------------------------------------------------- /src/pyqode_i18n.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | _dict = { 4 | "es": { 5 | "Edu CIAA MicroPython": "Edu CIAA MicroPython", 6 | "Open": "Abrir", 7 | "Save": "Guardar", 8 | "New": "Nuevo", 9 | "Run": "Ejecutar", 10 | "About": "Acerca de...", 11 | "Help": "Ayuda", 12 | "Terminal": "Terminal", 13 | "To Editor": "Al Editor", 14 | "Outline": "Simbolos", 15 | "Snipplets": "Trozos de codigo", 16 | "Download": "Grabar", 17 | "Undo": "Deshacer", 18 | "Redo": "Rehacer", 19 | "Cut": "Cortar", 20 | "Copy": "Copiar", 21 | "Paste": "Pegar", 22 | "Duplicate line": "Duplicar Linea", 23 | "Delete": "Borrar", 24 | "Indent": "Identar", 25 | "Un-indent": "Desidentar", 26 | "Go to line": "Ir a la linea", 27 | "Search": "Buscar", 28 | "Select": "Seleccionar", 29 | "Case": "Capitalización", 30 | "Go to assignments": "Ir a...", 31 | "Comment/Uncomment": "Comentar/Descomentar", 32 | "Show documentation": "Ver documentación", 33 | "Folding": "Plegar codigo", 34 | "Encodings": "Codificación", 35 | "Select word": "Seleccionar palabra", 36 | "Select extended word": "Seleccionar palabra extendida", 37 | "Matched select": "[TODO] Matched select", 38 | "Select line": "Seleccionar linea", 39 | "Select all": "Seleccionar todo", 40 | "Search and replace": "Buscar y reemplazar", 41 | "Find next": "Encontrar siguiente", 42 | "Find previous": "Encontrar anterior", 43 | "Convert to lower case": "Convertir a minusculas", 44 | "Convert to UPPER CASE": "Convertir a MAYUSCULAS", 45 | "Question": "Pregunta", 46 | "Document was modify": "El documento se ha modificado", 47 | "Save changes?": "¿Guardar los cambios?", 48 | "Save File": "Guardar Archivo", 49 | "Open File": "Abrir Archivo", 50 | "Python files (*.py);;All files (*)": "Archivos Python (*.py);;" 51 | "Todos los archivos (*)", 52 | "Serial Port:": "Puerto Serial:", 53 | "NewFile.py (%d)": "Nuevo.py (%d)", 54 | "Remote Name": "Nombre Remoto", 55 | "Select Serial Port": "Seleccionar Puerto Serie" 56 | }, 57 | "zh_TW": { 58 | "Edu CIAA MicroPython": "Edu CIAA MicroPython", 59 | "Open": "開啟", 60 | "Save": "儲存", 61 | "New": "新檔案", 62 | "Run": "執行", 63 | "About": "關於...", 64 | "Help": "幫助", 65 | "Terminal": "終端機", 66 | "To Editor": "到編輯器", 67 | "Outline": "大綱", 68 | "Snipplets": "片段", 69 | "Download": "下載", 70 | "Undo": "復原", 71 | "Redo": "重做", 72 | "Cut": "剪下", 73 | "Copy": "複製", 74 | "Paste": "貼上", 75 | "Duplicate line": "複製此行", 76 | "Delete": "刪除", 77 | "Indent": "縮排", 78 | "Un-indent": "取消縮排", 79 | "Go to line": "Go to line", 80 | "Search": "尋找", 81 | "Select": "選取", 82 | "Case": "Case", 83 | "Go to assignments": "Go to assignments", 84 | "Comment/Uncomment": "註解/取消註解", 85 | "Show documentation": "顯示文件", 86 | "Folding": "折疊", 87 | "Encodings": "編碼", 88 | "Select word": "選取字", 89 | "Select extended word": "選取延伸字", 90 | "Matched select": "[TODO] 匹配選取", 91 | "Select line": "選取行", 92 | "Select all": "選取全部", 93 | "Search and replace": "尋找和取代", 94 | "Find next": "找下一個", 95 | "Find previous": "找前一個", 96 | "Convert to lower case": "轉為小寫", 97 | "Convert to UPPER CASE": "轉為大寫", 98 | "Question": "問題", 99 | "Document was modify": "文件已經被修改", 100 | "Save changes?": "儲存修改?", 101 | "Save File": "儲存檔案", 102 | "Open File": "開啟檔案", 103 | "Python files (*.py);;All files (*)": "Python 檔案(*.py);;" 104 | "所有檔案 (*)", 105 | "Serial Port:": "序列埠:", 106 | "NewFile.py (%d)": "新檔案.py (%d)", 107 | "Remote Name": "遠端名稱", 108 | "Select Serial Port": "選取序列埠", 109 | "Device files": "裝置的檔案", 110 | "Refresh": "重新整理", 111 | "Device": "裝置", 112 | "Download to Device": "上傳到裝置" 113 | } 114 | } 115 | 116 | 117 | def tr(text, lang="es"): 118 | if lang in _dict and text in _dict[lang].keys(): 119 | return _dict[lang][text] 120 | else: 121 | return "*{}".format(text) 122 | -------------------------------------------------------------------------------- /src/server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Main server script for a pyqode.python backend. You can directly use this 5 | script in your application if it fits your needs or use it as a starting point 6 | for writing your own server. 7 | 8 | :: 9 | 10 | usage: server.py [-h] [-s [SYSPATH [SYSPATH ...]]] port 11 | 12 | positional arguments: 13 | port the local tcp port to use to run the server 14 | 15 | optional arguments: 16 | -h, --help show this help message and exit 17 | -s [SYSPATH [SYSPATH ...]], --syspath [SYSPATH [SYSPATH ...]] 18 | 19 | """ 20 | import argparse 21 | import logging 22 | import sys 23 | 24 | 25 | if __name__ == '__main__': 26 | """ 27 | Server process' entry point 28 | """ 29 | logging.basicConfig() 30 | # setup argument parser and parse command line args 31 | parser = argparse.ArgumentParser() 32 | parser.add_argument("port", help="the local tcp port to use to run " 33 | "the server") 34 | parser.add_argument('-s', '--syspath', nargs='*') 35 | args = parser.parse_args() 36 | 37 | # add user paths to sys.path 38 | if args.syspath: 39 | for path in args.syspath: 40 | print(('append path %s to sys.path' % path)) 41 | sys.path.append(path) 42 | 43 | from pyqode.core import backend 44 | from pyqode.python.backend.workers import JediCompletionProvider 45 | 46 | # setup completion providers 47 | backend.CodeCompletionWorker.providers.append(JediCompletionProvider()) 48 | backend.CodeCompletionWorker.providers.append( 49 | backend.DocumentWordsProvider()) 50 | 51 | # starts the server 52 | backend.serve_forever(args) 53 | -------------------------------------------------------------------------------- /src/termWidget.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import glob 3 | import pyte 4 | import serial 5 | import sys 6 | import threading 7 | import time 8 | 9 | import pyqode.qt.QtWidgets as QtWidgets 10 | import pyqode.qt.QtCore as QtCore 11 | import pyqode.qt.QtGui as QtGui 12 | from PyQt5.Qt import QApplication 13 | 14 | from myDef import i18n 15 | 16 | 17 | def serial_ports(): 18 | """ Lists serial port names 19 | :raises EnvironmentError: 20 | On unsupported or unknown platforms 21 | :returns: 22 | A list of the serial ports available on the system 23 | """ 24 | if sys.platform.startswith('win'): 25 | ports = ['COM%s' % (i + 1) for i in range(256)] 26 | elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'): 27 | # this excludes your current terminal "/dev/tty" 28 | ports = glob.glob('/dev/tty[A-Za-z]*') 29 | elif sys.platform.startswith('darwin'): 30 | ports = glob.glob('/dev/tty.*') 31 | else: 32 | raise EnvironmentError('Unsupported platform') 33 | result = [] 34 | for port in ports: 35 | try: 36 | s = serial.Serial(port) 37 | s.close() 38 | result.append(port) 39 | except (OSError, serial.SerialException): 40 | pass 41 | return result 42 | 43 | 44 | class Terminal(QtWidgets.QWidget): 45 | ''' 46 | classdocs 47 | ''' 48 | def __init__(self, parent=None): 49 | ''' 50 | Constructor 51 | ''' 52 | super(self.__class__, self).__init__(parent) 53 | self.setFont(QtGui.QFont({ 54 | 'win32': 'Consolas', 55 | 'linux': 'Monospace', 56 | 'darwin': 'Andale Mono' 57 | }.get(sys.platform, 'Courier'), 10)) 58 | self.setFocusPolicy(QtCore.Qt.ClickFocus) 59 | self.setStyleSheet("background-color : black; color : #cccccc;") 60 | self._workers = [] 61 | self._serial = None 62 | self._thread = None 63 | self._stream = pyte.Stream() 64 | self._vt = pyte.Screen(80, 24) 65 | self._stream.attach(self._vt) 66 | self._workers.append(self._processText) 67 | self._stop = threading.Event() 68 | 69 | 70 | def mousePressEvent(self, QMouseEvent): 71 | if QMouseEvent.button() == QtCore.Qt.LeftButton: 72 | #print("Left Button Clicked") 73 | pass 74 | elif QMouseEvent.button() == QtCore.Qt.RightButton: 75 | #print("Right Button Clicked") 76 | self.rightMenu(QMouseEvent.pos()) 77 | 78 | 79 | def rightMenu(self, position): 80 | menu = QtWidgets.QMenu() 81 | pasteAction = menu.addAction(i18n("Paste")) 82 | pasteAction.triggered.connect(self.paste) 83 | if not QApplication.clipboard().mimeData().hasText(): 84 | pasteAction.setEnabled(False) 85 | menu.exec_(self.mapToGlobal(position)) 86 | 87 | def paste(self): 88 | clipText = QApplication.clipboard().text() 89 | if clipText: 90 | self._serial.write(clipText.encode()) 91 | 92 | 93 | def resizeEvent(self, event): 94 | charSize = self.textRect(' ').size() 95 | lines = int(event.size().height() / charSize.height()) 96 | columns = int(event.size().width() / charSize.width()) 97 | self._vt.resize(lines, columns) 98 | self._vt.reset() 99 | 100 | def focusNextPrevChild(self, n): 101 | return False 102 | 103 | def close(self): 104 | self._stop.set() 105 | if self._thread and self._thread.isAlive(): 106 | self._thread.join() 107 | self._thread = None 108 | if self._serial: 109 | self._serial.close() 110 | 111 | def open(self, port, speed): 112 | self._stopThread() 113 | if type(self._serial) is serial.Serial: 114 | self._serial.close() 115 | try: 116 | self._serial = serial.Serial(port, speed, timeout=0.5) 117 | self._startThread() 118 | return True 119 | except serial.SerialException as e: 120 | print(e) 121 | return False 122 | 123 | def remoteExec(self, cmd, interceptor=None): 124 | if interceptor: 125 | self._workers.append(interceptor) 126 | cmd_b = cmd if isinstance(cmd, bytes) else bytes(cmd, encoding='utf8') 127 | # write command 128 | for i in range(0, len(cmd_b), 256): 129 | self._serial.write(cmd_b[i:min(i + 256, len(cmd_b))]) 130 | time.sleep(0.01) 131 | 132 | def _stopThread(self): 133 | self._stop.set() 134 | if self._thread and self._thread.isAlive(): 135 | self._thread.join() 136 | self._thread = None 137 | 138 | def _startThread(self): 139 | self._stop.clear() 140 | self._thread = threading.Thread(target=self._readThread) 141 | self._thread.setDaemon(1) 142 | self._thread.start() 143 | 144 | def _readThread(self): 145 | try: 146 | while not self._stop.is_set(): 147 | text = self._serial.read(self._serial.inWaiting() or 1) 148 | if text: 149 | self._workers = [w for w in self._workers if not w(text)] 150 | except Exception as e: 151 | print(e) 152 | 153 | def _processText(self, text): 154 | self._stream.feed(text.decode(errors='ignore')) 155 | self.update() 156 | return False 157 | 158 | def focusInEvent(self, event): 159 | self.repaint() 160 | 161 | def focusOutEvent(self, event): 162 | self.repaint() 163 | 164 | def paintEvent(self, event): 165 | p = QtGui.QPainter() 166 | p.begin(self) 167 | pal = self.palette() 168 | p.fillRect(QtCore.QRect(QtCore.QPoint(), self.size()), 169 | pal.color(pal.Background)) 170 | textSize = self.textRect(' ' * self._vt.columns).size() 171 | bound = QtCore.QRect(QtCore.QPoint(), textSize) 172 | flags = QtCore.Qt.AlignLeft | QtCore.Qt.AlignBottom 173 | for line in self._vt.display: 174 | p.drawText(bound, flags, line) 175 | bound.translate(0, bound.height()) 176 | if self.hasFocus(): 177 | p.fillRect(self.cursorRect(), pal.color(pal.Foreground)) 178 | else: 179 | p.drawRect(self.cursorRect()) 180 | p.end() 181 | 182 | def textRect(self, text): 183 | textSize = QtGui.QFontMetrics(self.font()).size(0, text) 184 | return QtCore.QRect(QtCore.QPoint(), textSize) 185 | 186 | def cursorRect(self): 187 | r = self.textRect(' ') 188 | r.moveTopLeft(QtCore.QPoint(0, 0) + 189 | QtCore.QPoint(self._vt.cursor.x * r.width(), 190 | self._vt.cursor.y * r.height())) 191 | return r 192 | 193 | def keyPressEvent(self, event): 194 | if self._serial and self._serial.isOpen(): 195 | try: 196 | text = { 197 | QtCore.Qt.Key_Tab: lambda x: b"\t", 198 | QtCore.Qt.Key_Backspace: lambda x: b"\x7f", 199 | QtCore.Qt.Key_Up: lambda x: b"\033[A", 200 | QtCore.Qt.Key_Down: lambda x: b"\033[B", 201 | QtCore.Qt.Key_Left: lambda x: b"\033[D", 202 | QtCore.Qt.Key_Right: lambda x: b"\033[C", 203 | }[event.key()](event.key()) 204 | except KeyError: 205 | text = bytes(event.text(), 'utf-8') 206 | if text: 207 | self._serial.write(text) 208 | event.accept() 209 | 210 | 211 | def selectPort(): 212 | d = QtWidgets.QDialog() 213 | l = QtWidgets.QVBoxLayout(d) 214 | combo = QtWidgets.QComboBox(d) 215 | combo.addItems(serial_ports()) 216 | ok = QtWidgets.QPushButton("Ok", d) 217 | ok.clicked.connect(d.close) 218 | l.addWidget(combo) 219 | l.addWidget(ok) 220 | d.exec_() 221 | return combo.currentText() 222 | 223 | 224 | def main(): 225 | app = QtWidgets.QApplication(sys.argv) 226 | w = Terminal() 227 | w.resize(640, 480) 228 | w.show() 229 | w.open(selectPort(), 115200) 230 | w.remoteExec('\x04') 231 | app.exec_() 232 | 233 | if __name__ == "__main__": 234 | main() 235 | -------------------------------------------------------------------------------- /src/uPyIDE.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import tendo.singleton 3 | import os 4 | import re 5 | import sys 6 | import glob 7 | import collections 8 | 9 | import pyqode.python.backend.server as server 10 | import pyqode.python.widgets as widgets 11 | import pyqode.core.widgets as wcore 12 | import pyqode.qt.QtCore as QtCore 13 | import pyqode.qt.QtWidgets as QtWidgets 14 | import pyqode.qt.QtGui as QtGui 15 | import pyqode_i18n 16 | import termWidget 17 | import xml.etree.ElementTree as ElementTree 18 | 19 | import markdown 20 | 21 | from myDef import i18n 22 | # from docutils.parsers.rst.directives import path 23 | 24 | 25 | me = tendo.singleton.SingleInstance() 26 | 27 | __version__ = '1.0' 28 | 29 | 30 | 31 | def executable_path(): 32 | if hasattr(sys, 'frozen'): 33 | return os.path.dirname(sys.executable) 34 | else: 35 | return os.path.dirname(sys.argv[0]) 36 | 37 | 38 | def share(): 39 | return os.path.abspath(os.path.join(executable_path(), 40 | '..', 'share', 'uPyIDE')) 41 | 42 | 43 | def fakelibs(): 44 | return os.path.join(share(), 'fakelibs') 45 | 46 | 47 | def icon(name): 48 | path = os.path.join(share(), 'images', '{}.png'.format(name)) 49 | return QtGui.QIcon(path) 50 | 51 | 52 | def backend_interpreter(): 53 | if getattr(sys, 'frozen', False): 54 | return '' 55 | else: 56 | return sys.executable 57 | 58 | 59 | def completion_server(): 60 | if getattr(sys, 'frozen', False): 61 | server_path = os.path.join(executable_path(), 'server.exe') 62 | print(server_path) 63 | return server_path 64 | else: 65 | return server.__file__ 66 | 67 | 68 | def about_pixmap(): 69 | return QtGui.QPixmap(os.path.join(share(), 'images', 'splash.png')) 70 | 71 | 72 | class WidgetSpacer(QtWidgets.QWidget): 73 | def __init__(self, parent, wmax=None): 74 | super(WidgetSpacer, self).__init__(parent) 75 | self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, 76 | QtWidgets.QSizePolicy.Expanding) 77 | if wmax: 78 | self.setMaximumWidth(wmax) 79 | 80 | 81 | class PortSelector(QtWidgets.QComboBox): 82 | def __init__(self, parent): 83 | super(self.__class__, self).__init__(parent) 84 | self.widget = parent 85 | portList = termWidget.serial_ports() 86 | print(portList) 87 | self.addItems(portList) 88 | self.currentIndexChanged.connect(self.onChange) 89 | self.setCurrentIndex(0) 90 | # self.onChange(0) 91 | 92 | @QtCore.Slot(int) 93 | def onChange(self, n): 94 | if self.currentText(): 95 | port = self.currentText() 96 | self.widget.setPort(port) 97 | 98 | 99 | class SnipplerWidget(QtWidgets.QDockWidget): 100 | def __init__(self, parent): 101 | super(SnipplerWidget, self).__init__(i18n('Snipplets'), parent) 102 | self.setWindowTitle(i18n("Snipplets")) 103 | self.snippletView = QtWidgets.QListWidget(self) 104 | self.setWidget(self.snippletView) 105 | self.loadSnipplets() 106 | self.snippletView.itemDoubleClicked.connect(self._insertToParent) 107 | 108 | def _insertToParent(self, item): 109 | if self.parent().tabber.active_editor: 110 | self.parent().tabber.active_editor.insertPlainText(item.toolTip()) 111 | 112 | def addSnipplet(self, description, contents): 113 | item = QtWidgets.QListWidgetItem(self.snippletView) 114 | item.setText(description) 115 | item.setToolTip(contents) 116 | 117 | def loadSnippletFrom(self, inp): 118 | xml = ElementTree.fromstring(inp) if type(inp) is str else \ 119 | ElementTree.parse(inp).getroot() 120 | for child in xml: 121 | self.addSnipplet(child.attrib["name"], child.text) 122 | 123 | def loadCodeSnipplet(self, source): 124 | with open(source) as f: 125 | s = f.read() 126 | r = re.compile(r'^# Description: (.*)[\r\n]*') 127 | description = ''.join(re.findall(r, s)) 128 | contents = re.sub(r, '', s) 129 | if description and contents: 130 | self.addSnipplet(description, contents) 131 | 132 | @QtCore.Slot() 133 | def loadSnipplets(self): 134 | self.snippletView.setStyleSheet('''QToolTip { 135 | font-family: "monospace"; 136 | }''') 137 | with open(os.path.join(share(), 'snipplet', 'snipplets.xml')) as f: 138 | self.loadSnippletFrom(f) 139 | snipplet_glob = os.path.join(share(), 'snipplet', '*.py') 140 | for source in glob.glob(snipplet_glob): 141 | self.loadCodeSnipplet(source) 142 | 143 | class DeviceFilesWidget(QtWidgets.QDockWidget): 144 | def __init__(self, parent): 145 | super(DeviceFilesWidget, self).__init__(i18n('Device files'), parent) 146 | self.setWindowTitle(i18n("Device files")) 147 | widget = QtWidgets.QWidget(self) 148 | vlayout = QtWidgets.QVBoxLayout() 149 | self.toolbar = QtWidgets.QToolBar(self) 150 | self.toolbar.addAction(i18n("Refresh"), self.loadRemoteFiles) 151 | self.toolbar.addAction(icon("download"), i18n("Download to Device"), self.downloadFile) 152 | self.filesView = QtWidgets.QTreeWidget(self) 153 | self.filesView.header().close() 154 | self.deviceItem = QtWidgets.QTreeWidgetItem(0) 155 | self.deviceItem.setText(0,i18n("Device")) 156 | self.filesView.addTopLevelItem(self.deviceItem) 157 | vlayout.addWidget(self.toolbar) 158 | vlayout.addWidget(self.filesView) 159 | widget.setLayout(vlayout) 160 | self.setWidget(widget) 161 | 162 | @QtCore.Slot() 163 | def loadRemoteFiles(self): 164 | print('TODO: load Remote File list') 165 | pass 166 | @QtCore.Slot() 167 | def downloadFile(self): 168 | #print(self.parent().windowTitle()) 169 | print('TODO: download selected File') 170 | pass 171 | 172 | class MainWindow(QtWidgets.QMainWindow): 173 | onListDir = QtCore.Signal(str) 174 | 175 | def __init__(self): 176 | QtWidgets.QMainWindow.__init__(self) 177 | self.setWindowTitle(i18n("Edu CIAA MicroPython")) 178 | self.cwd = QtCore.QDir.homePath() 179 | self.tabber = wcore.TabWidget(self) 180 | self.term = termWidget.Terminal(self) 181 | self.outline = widgets.PyOutlineTreeWidget() 182 | self.dock_outline = QtWidgets.QDockWidget(i18n('Outline')) 183 | self.dock_outline.setWidget(self.outline) 184 | self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dock_outline) 185 | self.snippler = SnipplerWidget(self) 186 | self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.snippler) 187 | self.deviceFiles = DeviceFilesWidget(self) 188 | self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.deviceFiles) 189 | self.stack = QtWidgets.QStackedWidget(self) 190 | self.stack.addWidget(self.tabber) 191 | self.stack.addWidget(self.term) 192 | self.setCentralWidget(self.stack) 193 | self.makeAppToolBar() 194 | self.resize(1024, 600) 195 | self.onListDir.connect(lambda l: self._showDir(l)) 196 | self.tabber.currentChanged.connect(self.actualizeOutline) 197 | self.fileNew() 198 | self.portSelector.onChange(0) 199 | 200 | def actualizeOutline(self, n): 201 | self.outline.set_editor(self.tabber.active_editor) 202 | self.i18n() 203 | 204 | def i18n(self, actions=None): 205 | if not self.tabber.active_editor: 206 | return 207 | if not actions: 208 | actions = self.tabber.active_editor.actions() 209 | for action in actions: 210 | if not action.isSeparator(): 211 | action.setText(pyqode_i18n.tr(action.text())) 212 | if action.menu(): 213 | self.i18n(action.menu().actions()) 214 | 215 | def terminate(self): 216 | self.term.close() 217 | 218 | def makeAppToolBar(self): 219 | bar = QtWidgets.QToolBar('Toolbar', self) 220 | bar.setIconSize(QtCore.QSize(48, 48)) 221 | bar.addAction(icon("document-new"), i18n("New"), self.fileNew) 222 | bar.addAction(icon("document-open"), i18n("Open"), self.fileOpen) 223 | bar.addAction(icon("document-save"), i18n("Save"), self.fileSave) 224 | bar.addWidget(WidgetSpacer(self)) 225 | bar.addWidget(QtWidgets.QLabel(i18n("Serial Port:"))) 226 | bar.addWidget(WidgetSpacer(self, 12)) 227 | self.portSelector = PortSelector(self) 228 | bar.addWidget(self.portSelector) 229 | self.portSelector.setToolTip(i18n("Select Serial Port")) 230 | self.runAction = bar.addAction(icon("run"), i18n("Run"), self.progRun) 231 | self.runAction.setEnabled(False) 232 | self.dlAction = bar.addAction(icon("download"), i18n("Download"), 233 | self.progDownload) 234 | self.dlAction.setEnabled(False) 235 | self.termAction = bar.addAction(icon("terminal"), i18n("Terminal"), 236 | self.openTerm) 237 | self.termAction.setEnabled(False) 238 | self.termAction.setCheckable(True) 239 | bar.addAction(icon("about"), i18n("Help"), self.showhelp) 240 | self.addToolBar(bar) 241 | 242 | def _htmlhelp(self): 243 | return os.path.abspath(os.path.join(share(), 'help.html')) 244 | 245 | def _mdhelp(self): 246 | return os.path.abspath(os.path.join(share(), 'help.md')) 247 | 248 | def _cssfile(self): 249 | return os.path.abspath(os.path.join(share(), 'help.css')) 250 | 251 | def showhelp(self): 252 | dlg = QtWidgets.QDialog(self) 253 | dlg.setWindowTitle(i18n('Help')) 254 | l = QtWidgets.QVBoxLayout(dlg) 255 | l.setContentsMargins(6, 6, 6, 6) 256 | tabWidget = QtWidgets.QTabWidget(dlg) 257 | buttonBar = QtWidgets.QDialogButtonBox(dlg) 258 | buttonBar.addButton(QtWidgets.QDialogButtonBox.Close) 259 | buttonBar.accepted.connect(dlg.close) 260 | buttonBar.rejected.connect(dlg.close) 261 | l.addWidget(tabWidget) 262 | l.addWidget(buttonBar) 263 | tv = QtWidgets.QTextBrowser(tabWidget) 264 | image = QtWidgets.QLabel(tabWidget) 265 | image.setPixmap(about_pixmap()) 266 | tabWidget.addTab(image, i18n('About')) 267 | tabWidget.addTab(tv, i18n('Help')) 268 | with open(self._cssfile()) as f: 269 | tv.document().setDefaultStyleSheet(f.read()) 270 | try: 271 | with open(self._mdhelp()) as f: 272 | tv.document().setHtml(markdown.markdown(f.read())) 273 | except: 274 | try: 275 | with open(self._htmlhelp()) as f: 276 | tv.document().setHtml(f.read()) 277 | except: 278 | tv.setHtml("No help") 279 | dlg.exec_() 280 | 281 | def terminalMenu(self): 282 | m = QtWidgets.QMenu(self) 283 | g = QtWidgets.QActionGroup(m) 284 | g.triggered.connect(lambda a: self.setPort(a.text())) 285 | for s in termWidget.serial_ports(): 286 | a = m.addAction(s) 287 | g.addAction(a) 288 | a.setCheckable(True) 289 | if g.actions(): 290 | g.actions()[0].setChecked(True) 291 | self.setPort(g.actions()[0].text()) 292 | return m 293 | 294 | def setPort(self, port): 295 | en = self.term.open(port, 115200) 296 | [i.setEnabled(en) for i in (self.dlAction, 297 | self.runAction, 298 | self.termAction)] 299 | 300 | def closeEvent(self, event): 301 | self.tabber.closeEvent(event) 302 | if event.isAccepted(): 303 | self.terminate() 304 | 305 | def createEditor(self): 306 | return widgets.PyCodeEdit(interpreter=backend_interpreter(), 307 | server_script=completion_server(), 308 | args=['-s', fakelibs()]) 309 | 310 | def fileNew(self): 311 | code_edit = self.createEditor() 312 | i = self.tabber.add_code_edit(code_edit, i18n("NewFile.py (%d)")) 313 | self.tabber.setCurrentIndex(i) 314 | 315 | def dirtySaveDischartCancel(self): 316 | d = QtWidgets.QMessageBox() 317 | d.setWindowTitle(i18n("Question")) 318 | d.setText(i18n("Document was modify")) 319 | d.setInformativeText(i18n("Save changes?")) 320 | d.setIcon(QtWidgets.QMessageBox.Question) 321 | d.setStandardButtons(QtWidgets.QMessageBox.Save | 322 | QtWidgets.QMessageBox.Discard | 323 | QtWidgets.QMessageBox.Cancel) 324 | return d.exec_() 325 | 326 | def dirtySaveCancel(self): 327 | d = QtWidgets.QMessageBox() 328 | d.setWindowTitle(i18n("Question")) 329 | d.setText(i18n("Document was modify")) 330 | d.setInformativeText(i18n("Save changes?")) 331 | d.setIcon(QtWidgets.QMessageBox.Question) 332 | d.setStandardButtons(QtWidgets.QMessageBox.Save | 333 | QtWidgets.QMessageBox.Cancel) 334 | return d.exec_() 335 | 336 | def fileOpen(self): 337 | name, dummy = QtWidgets.QFileDialog.getOpenFileName( 338 | self, i18n("Open File"), self.cwd, 339 | i18n("Python files (*.py);;All files (*)")) 340 | if name: 341 | code_edit = self.createEditor() 342 | code_edit.file.open(name) 343 | i = self.tabber.add_code_edit(code_edit) 344 | self.tabber.setCurrentIndex(i) 345 | self.cwd = os.path.dirname(name) 346 | 347 | def fileSave(self): 348 | ed = self.tabber.active_editor 349 | if not ed: 350 | return False 351 | is_new = ed.file.path.startswith(i18n('NewFile.py (%d)') 352 | .replace(' (%d)', '')) 353 | if not ed.file.path or is_new: 354 | path, dummy = QtWidgets.QFileDialog. \ 355 | getSaveFileName(self, i18n("Save File"), self.cwd, 356 | i18n("Python files (*.py);;All files (*)")) 357 | else: 358 | path = ed.file.path 359 | if not path: 360 | return False 361 | old = self.tabber.currentIndex() 362 | self.tabber.setCurrentWidget(ed) 363 | self.tabber.save_current(path) 364 | self.tabber.setCurrentIndex(old) 365 | return True 366 | 367 | def openTerm(self): 368 | if self.termAction.isChecked(): 369 | self.stack.setCurrentIndex(1) 370 | self.termAction.setIcon(icon('terminal-out')) 371 | self.termAction.setText(i18n('To Editor')) 372 | self.term.setFocus() 373 | # self.term.remoteExec(b'\x04') 374 | else: 375 | self.termAction.setIcon(icon('terminal')) 376 | self.termAction.setText(i18n('Terminal')) 377 | self.stack.setCurrentIndex(0) 378 | 379 | def progRun(self): 380 | self._targetExec(self.tabber.active_editor.toPlainText()) 381 | self.termAction.setChecked(True) 382 | self.openTerm() 383 | 384 | def _targetExec(self, script, continuation=None): 385 | def progrun2(text): 386 | # print("{} {}".format(4, progrun2.text)) 387 | progrun2.text += text 388 | if progrun2.text.endswith(b'\x04>'): 389 | # print("{} {}".format(5, progrun2.text)) 390 | if isinstance(continuation, collections.Callable): 391 | continuation(progrun2.text) 392 | return True 393 | return False 394 | 395 | def progrun1(text): 396 | progrun1.text += text 397 | # print("{} {}".format(2, progrun1.text)) 398 | if progrun1.text.endswith(b'to exit\r\n>'): 399 | progrun2.text = b'' 400 | # print("{} {}".format(3, progrun1.text)) 401 | cmd = 'print("\033c")\r{}\r\x04\x02'.format(script) 402 | # print("{} {}".format(3.5, cmd)) 403 | self.term.remoteExec(bytes(cmd, 'utf-8'), progrun2) 404 | return True 405 | return False 406 | progrun1.text = b'' 407 | # print(1) 408 | self.term.remoteExec(b'\r\x03\x03\r\x01', progrun1) 409 | 410 | def showDir(self): 411 | def finished(raw): 412 | text = ''.join(re.findall(r"(\[.*?\])", raw.decode())) 413 | print((raw, text)) 414 | self.onListDir.emit(text) 415 | self._targetExec('print(os.listdir())', finished) 416 | 417 | def _showDir(self, text): 418 | items = eval(text) 419 | d = QtWidgets.QDialog(self) 420 | l = QtWidgets.QVBoxLayout(d) 421 | h = QtWidgets.QListWidget(d) 422 | l.addWidget(h) 423 | h.addItems(items) 424 | h.itemClicked.connect(d.accept) 425 | d.exec_() 426 | 427 | def _writeRemoteFile(self, local_name): 428 | '''upload local file to remote device (target board)''' 429 | def finished(raw): 430 | print(('_writeRemoteFile terminated: ', raw)) 431 | name = os.path.basename(local_name) 432 | name, ok = QtWidgets.QInputDialog.getText(self, i18n("Download"), 433 | i18n("Remote Name"), 434 | text=name) 435 | if not ok: 436 | return 437 | remote_name = '/flash/{}'.format(name) 438 | if os.path.exists(local_name): 439 | with open(local_name, 'rb') as f: 440 | data = f.read() 441 | else: 442 | data = self.tabber.active_editor.toPlainText() 443 | cmd = "with open(\"{}\", 'wb') as f:\r" \ 444 | " f.write({})".format(remote_name, repr(data)) 445 | print(("Writing remote to ", remote_name, repr(data))) 446 | print(("--------------\n", cmd, "\n--------------")) 447 | self._targetExec(cmd, finished) 448 | 449 | def progDownload(self): 450 | self._writeRemoteFile(self.tabber.active_editor.file.path) 451 | 452 | global app 453 | 454 | 455 | def main(): 456 | app = QtWidgets.QApplication(sys.argv) 457 | app.setQuitOnLastWindowClosed(True) 458 | splash = QtWidgets.QSplashScreen() 459 | splash.setPixmap(about_pixmap()) 460 | splash.show() 461 | 462 | def do_app(): 463 | splash.close() 464 | w = MainWindow() 465 | w.show() 466 | QtCore.QTimer.singleShot(2000, do_app) 467 | sys.exit(app.exec_()) 468 | 469 | if __name__ == "__main__": 470 | main() 471 | -------------------------------------------------------------------------------- /svg2png.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set BASE=%~dp0 3 | set S=%BASE%src\images\ 4 | set D=%BASE%share\uPyIDE\images\ 5 | set PROG="%ProgramFiles%\Inkscape\inkscape.exe" 6 | 7 | for %%f in (%S%*.svg) DO ( 8 | ECHO convert %%f to %D%%%~nf.png 9 | %PROG% -z %%f -e %D%%%~nf.png 10 | ) 11 | pause 12 | --------------------------------------------------------------------------------