Fri, 16 Aug 2019 17:17:32 +0200
MicroPythonWidget: added menu entries to cross compile a selectable Python file or the current editor to a .mpy file.
--- a/eric6/MicroPython/MicroPythonWidget.py Thu Aug 15 17:19:28 2019 +0200 +++ b/eric6/MicroPython/MicroPythonWidget.py Fri Aug 16 17:17:32 2019 +0200 @@ -11,6 +11,7 @@ import re import time +import os from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QPoint, QEvent from PyQt5.QtGui import QColor, QKeySequence, QTextCursor, QBrush @@ -22,6 +23,7 @@ from E5Gui.E5ZoomWidget import E5ZoomWidget from E5Gui import E5MessageBox, E5FileDialog from E5Gui.E5Application import e5App +from E5Gui.E5ProcessDialog import E5ProcessDialog from .Ui_MicroPythonWidget import Ui_MicroPythonWidget @@ -41,6 +43,7 @@ import Globals import UI.PixmapCache import Preferences +import Utilities # ANSI Colors (see https://en.wikipedia.org/wiki/ANSI_escape_code) AnsiColorSchemes = { @@ -1087,7 +1090,6 @@ else: hasTime = False - # TODO: add menu entry to cross-compile a .py file (using mpy-cross) act = self.__superMenu.addAction( self.tr("Show Version"), self.__showDeviceVersion) act.setEnabled(self.__connected) @@ -1105,6 +1107,14 @@ self.__superMenu.addAction( self.tr("Show Local Time"), self.__showLocalTime) self.__superMenu.addSeparator() + if not Globals.isWindowsPlatform(): + self.__superMenu.addAction( + self.tr("Compile Python File"), self.__compileFile2Mpy) + act = self.__superMenu.addAction( + self.tr("Compile Current Editor"), self.__compileEditor2Mpy) + aw = e5App().getObject("ViewManager").activeWindow() + act.setEnabled(bool(aw)) + self.__superMenu.addSeparator() if self.__device: self.__device.addDeviceMenuEntries(self.__superMenu) @@ -1261,3 +1271,89 @@ self.tr("<p>There was an error communicating with the connected" " device.</p><p>Method: {0}</p><p>Message: {1}</p>") .format(method, error)) + + def __crossCompile(self, pythonFile="", title=""): + """ + Private method to cross compile a Python file to a .mpy file. + + @param pythonFile name of the Python file to be compiled + @type str + @param title title for the various dialogs + @type str + """ + program = Preferences.getMicroPython("MpyCrossCompiler") + if not program: + program = "mpy-cross" + if not Utilities.isinpath(program): + E5MessageBox.critical( + self, + title, + self.tr("""The MicroPython cross compiler""" + """ <b>mpy-cross</b> cannot be found. Ensure it""" + """ is in the search path or configure it on""" + """ the MicroPython configuration page.""")) + return + + if not pythonFile: + defaultDirectory = "" + aw = e5App().getObject("ViewManager").activeWindow() + if aw: + fn = aw.getFileName() + if fn: + defaultDirectory = os.path.dirname(fn) + if not defaultDirectory: + defaultDirectory = Preferences.getMultiProject("Workspace") + pythonFile = E5FileDialog.getOpenFileName( + self, + title, + defaultDirectory, + self.tr("Python Files (*.py);;All Files (*)")) + if not pythonFile: + # user cancelled + return + + if not os.path.exists(pythonFile): + E5MessageBox.critical( + self, + title, + self.tr("""The Python file <b>{0}</b> does not exist.""" + """ Aborting...""").format(pythonFile)) + return + + compileArgs = [ + pythonFile, + ] + dlg = E5ProcessDialog(self.tr("'mpy-cross' Output"), title) + res = dlg.startProcess(program, compileArgs) + if res: + dlg.exec_() + + @pyqtSlot() + def __compileFile2Mpy(self): + """ + Private slot to cross compile a Python file (*.py) to a .mpy file. + """ + self.__crossCompile(title=self.tr("Compile Python File")) + + @pyqtSlot() + def __compileEditor2Mpy(self): + """ + Private slot to cross compile the current editor to a .mpy file. + """ + aw = e5App().getObject("ViewManager").activeWindow() + if not aw.checkDirty(): + # editor still has unsaved changes, abort... + return + if not aw.isPyFile(): + # no Python file + E5MessageBox.critical( + self, + self.tr("Compile Current Editor"), + self.tr("""The current editor does not contain a Python""" + """ file. Aborting...""")) + return + + self.__crossCompile( + pythonFile=aw.getFileName(), + title=self.tr("Compile Current Editor") + )
--- a/eric6/Preferences/ConfigurationPages/MicroPythonPage.py Thu Aug 15 17:19:28 2019 +0200 +++ b/eric6/Preferences/ConfigurationPages/MicroPythonPage.py Fri Aug 16 17:17:32 2019 +0200 @@ -9,6 +9,8 @@ from __future__ import unicode_literals +from E5Gui.E5PathPicker import E5PathPickerModes + from .ConfigurationPageBase import ConfigurationPageBase from .Ui_MicroPythonPage import Ui_MicroPythonPage @@ -34,6 +36,9 @@ self.colorSchemeComboBox.addItems(sorted(AnsiColorSchemes.keys())) + self.mpyCrossPicker.setMode(E5PathPickerModes.OpenFileMode) + self.mpyCrossPicker.setFilters(self.tr("All Files (*)")) + # set initial values self.timeoutSpinBox.setValue( Preferences.getMicroPython("SerialTimeout") / 1000) @@ -45,6 +50,8 @@ Preferences.getMicroPython("ColorScheme"))) self.replWrapCheckBox.setChecked( Preferences.getMicroPython("ReplLineWrap")) + self.mpyCrossPicker.setText( + Preferences.getMicroPython("MpyCrossCompiler")) def save(self): """ @@ -59,6 +66,8 @@ "ColorScheme", self.colorSchemeComboBox.currentText()) Preferences.setMicroPython( "ReplLineWrap", self.replWrapCheckBox.isChecked()) + Preferences.setMicroPython( + "MpyCrossCompiler", self.mpyCrossPicker.text()) def create(dlg): @@ -68,5 +77,4 @@ @param dlg reference to the configuration dialog @return reference to the instantiated page (ConfigurationPageBase) """ - page = MicroPythonPage() - return page + return MicroPythonPage()
--- a/eric6/Preferences/ConfigurationPages/MicroPythonPage.ui Thu Aug 15 17:19:28 2019 +0200 +++ b/eric6/Preferences/ConfigurationPages/MicroPythonPage.ui Fri Aug 16 17:17:32 2019 +0200 @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>477</width> - <height>346</height> + <width>476</width> + <height>356</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout"> @@ -135,6 +135,38 @@ </widget> </item> <item> + <widget class="QGroupBox" name="groupBox_3"> + <property name="title"> + <string>MPY Cross Compiler</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Program:</string> + </property> + </widget> + </item> + <item> + <widget class="E5PathPicker" name="mpyCrossPicker" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::WheelFocus</enum> + </property> + <property name="toolTip"> + <string>Enter the path of the cross compiler executable</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> <spacer name="verticalSpacer"> <property name="orientation"> <enum>Qt::Vertical</enum> @@ -149,6 +181,14 @@ </item> </layout> </widget> + <customwidgets> + <customwidget> + <class>E5PathPicker</class> + <extends>QWidget</extends> + <header>E5Gui/E5PathPicker.h</header> + <container>1</container> + </customwidget> + </customwidgets> <tabstops> <tabstop>timeoutSpinBox</tabstop> <tabstop>syncTimeCheckBox</tabstop>
--- a/eric6/Preferences/__init__.py Thu Aug 15 17:19:28 2019 +0200 +++ b/eric6/Preferences/__init__.py Fri Aug 16 17:17:32 2019 +0200 @@ -1597,6 +1597,7 @@ "SyncTimeAfterConnect": True, "ShowHiddenLocal": True, "ShowHiddenDevice": True, + "MpyCrossCompiler": "", # path of the mpy cross compiler } if Globals.isWindowsPlatform(): microPythonDefaults["ColorScheme"] = "Windows 10"