Added the files forgotten in the last commit.

Sat, 06 Feb 2021 19:17:25 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 06 Feb 2021 19:17:25 +0100
changeset 8080
218ca8019eb8
parent 8079
331e717c458e
child 8081
e0087e542717

Added the files forgotten in the last commit.

eric6/MicroPython/AddEditDevicesDialog.py file | annotate | diff | comparison | revisions
eric6/MicroPython/AddEditDevicesDialog.ui file | annotate | diff | comparison | revisions
eric6/MicroPython/UnknownDevicesDialog.py file | annotate | diff | comparison | revisions
eric6/MicroPython/UnknownDevicesDialog.ui file | annotate | diff | comparison | revisions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/MicroPython/AddEditDevicesDialog.py	Sat Feb 06 19:17:25 2021 +0100
@@ -0,0 +1,126 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2021 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to add or edit data of unknown MicroPython
+devices.
+"""
+
+from PyQt5.QtCore import pyqtSlot, Qt, QUrl, QUrlQuery
+from PyQt5.QtGui import QDesktopServices
+from PyQt5.QtWidgets import QDialog, QDialogButtonBox
+
+from .Ui_AddEditDevicesDialog import Ui_AddEditDevicesDialog
+
+from .MicroPythonDevices import getSupportedDevices
+
+from UI.Info import BugAddress
+
+
+class AddEditDevicesDialog(QDialog, Ui_AddEditDevicesDialog):
+    """
+    Class implementing a dialog to add or edit data of unknown MicroPython
+    devices.
+    """
+    def __init__(self, vid=0, pid=0, description=0, deviceData=None,
+                 parent=None):
+        """
+        Constructor
+        
+        Note: Either vid and pid and description or deviceData dictionary
+        must be given.
+        
+        @param vid vendor ID of the device (defaults to 0)
+        @type int (optional)
+        @param pid product ID of the device (defaults to 0)
+        @type int (optional)
+        @param description description for the device (defaults to "")
+        @type str (optional)
+        @param deviceData type of the device (defaults to None)
+        @type dict (optional)
+        @param parent reference to the parent widget (defaults to None)
+        @type QWidget (optional)
+        """
+        super(AddEditDevicesDialog, self).__init__(parent)
+        self.setupUi(self)
+        
+        # populate the device type combo box
+        self.deviceTypeComboBox.addItem("", "")
+        for board, desc in sorted(getSupportedDevices(), key=lambda x: x[1]):
+            self.deviceTypeComboBox.addItem(desc, board)
+        
+        if deviceData is not None:
+            self.vidEdit.setText("0x{0:04x}".format(deviceData["vid"]))
+            self.pidEdit.setText("0x{0:04x}".format(deviceData["pid"]))
+            self.descriptionEdit.setText(deviceData["description"])
+            self.deviceTypeComboBox.setCurrentIndex(
+                self.deviceTypeComboBox.findData(deviceData["type"]))
+            self.dataVolumeEdit.setText(deviceData["data_volume"])
+            self.flashVolumeEdit.setText(deviceData["flash_volume"])
+        else:
+            self.vidEdit.setText("0x{0:04x}".format(vid))
+            self.pidEdit.setText("0x{0:04x}".format(pid))
+            self.descriptionEdit.setText(description)
+            self.deviceTypeComboBox.setCurrentText("")
+            self.dataVolumeEdit.setText("")
+            self.flashVolumeEdit.setText("")
+        
+        self.deviceTypeComboBox.setFocus(Qt.OtherFocusReason)
+        
+        msh = self.minimumSizeHint()
+        self.resize(max(self.width(), msh.width()), msh.height())
+    
+    @pyqtSlot(int)
+    def on_deviceTypeComboBox_currentIndexChanged(self, index):
+        """
+        Private slot to handle the selection of a device type.
+        
+        @param index index of the current item
+        @type int
+        """
+        board = self.deviceTypeComboBox.currentData()
+        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(bool(board))
+        self.reportButton.setEnabled(bool(board))
+    
+    @pyqtSlot()
+    def on_reportButton_clicked(self):
+        """
+        Private slot to report the entered data to the eric-bugs email address.
+        """
+        body = "\r\n".join([
+            "This is an unknow MicroPython device. Please add it.",
+            "",
+            "VID: {0}".format(self.vidEdit.text()),
+            "PID: {0}".format(self.pidEdit.text()),
+            "Description: {0}".format(self.descriptionEdit.text()),
+            "Device Type: {0}".format(self.deviceTypeComboBox.currentData()),
+            "Data Volume: {0}".format(self.dataVolumeEdit.text().strip()),
+            "Flash Volume: {0}".format(self.flashVolumeEdit.text().strip()),
+        ])
+        
+        urlQuery = QUrlQuery()
+        urlQuery.addQueryItem("subject", "Unsupported MicroPython Device")
+        urlQuery.addQueryItem("body", body)
+        
+        url = QUrl("mailto:{0}".format(BugAddress))
+        url.setQuery(urlQuery)
+        
+        QDesktopServices.openUrl(url)
+    
+    def getDeviceDict(self):
+        """
+        Public method to get the entered data as a dictionary.
+        
+        @return dictionary containing the entered data
+        @rtype dict
+        """
+        return {
+            "vid": int(self.vidEdit.text(), 16),
+            "pid": int(self.pidEdit.text(), 16),
+            "description": self.descriptionEdit.text(),
+            "type": self.deviceTypeComboBox.currentData(),
+            "data_volume": self.dataVolumeEdit.text().strip(),
+            "flash_volume": self.flashVolumeEdit.text().strip(),
+        }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/MicroPython/AddEditDevicesDialog.ui	Sat Feb 06 19:17:25 2021 +0100
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AddEditDevicesDialog</class>
+ <widget class="QDialog" name="AddEditDevicesDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>500</width>
+    <height>270</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Add Unknown Device</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Vendor ID:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="QLineEdit" name="vidEdit">
+     <property name="readOnly">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="label_2">
+     <property name="text">
+      <string>Product ID:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="QLineEdit" name="pidEdit">
+     <property name="readOnly">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0">
+    <widget class="QLabel" name="label_3">
+     <property name="text">
+      <string>Description:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="1">
+    <widget class="QLineEdit" name="descriptionEdit">
+     <property name="readOnly">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="0">
+    <widget class="QLabel" name="label_4">
+     <property name="text">
+      <string>Device Type:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="1">
+    <widget class="QComboBox" name="deviceTypeComboBox">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="toolTip">
+      <string>Select the device type</string>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="0">
+    <widget class="QLabel" name="label_5">
+     <property name="text">
+      <string>Data Volume:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="1">
+    <widget class="QLineEdit" name="dataVolumeEdit">
+     <property name="toolTip">
+      <string>Enter the volume name used for direct acces to the device</string>
+     </property>
+     <property name="clearButtonEnabled">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="0">
+    <widget class="QLabel" name="label_6">
+     <property name="text">
+      <string>Flash Volume:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="1">
+    <widget class="QLineEdit" name="flashVolumeEdit">
+     <property name="toolTip">
+      <string>Enter the volume name used for flashing if this device supports UF2</string>
+     </property>
+     <property name="clearButtonEnabled">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="6" column="0" colspan="2">
+    <widget class="QPushButton" name="reportButton">
+     <property name="toolTip">
+      <string>Press to report the entered data via email</string>
+     </property>
+     <property name="text">
+      <string>Report Data</string>
+     </property>
+    </widget>
+   </item>
+   <item row="7" column="0" colspan="2">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>vidEdit</tabstop>
+  <tabstop>pidEdit</tabstop>
+  <tabstop>descriptionEdit</tabstop>
+  <tabstop>deviceTypeComboBox</tabstop>
+  <tabstop>dataVolumeEdit</tabstop>
+  <tabstop>flashVolumeEdit</tabstop>
+  <tabstop>reportButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>AddEditDevicesDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>AddEditDevicesDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/MicroPython/UnknownDevicesDialog.py	Sat Feb 06 19:17:25 2021 +0100
@@ -0,0 +1,256 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2021 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to manage the list of unknown devices.
+"""
+
+from PyQt5.QtCore import pyqtSlot, Qt, QUrl, QUrlQuery
+from PyQt5.QtGui import QDesktopServices
+from PyQt5.QtWidgets import QDialog, QListWidgetItem
+
+from E5Gui import E5MessageBox
+
+from .Ui_UnknownDevicesDialog import Ui_UnknownDevicesDialog
+
+import Preferences
+from UI.Info import BugAddress
+
+
+class UnknownDevicesDialog(QDialog, Ui_UnknownDevicesDialog):
+    """
+    Class implementing a dialog to manage the list of unknown devices.
+    """
+    DeviceDataRole = Qt.UserRole
+    ModifiedRole = Qt.UserRole + 1
+    
+    def __init__(self, parent=None):
+        """
+        Constructor
+        
+        @param parent reference to the parent widget (defaults to None)
+        @type QWidget (optional)
+        """
+        super(UnknownDevicesDialog, self).__init__(parent)
+        self.setupUi(self)
+        
+        self.__loadDevices()
+    
+    def __loadDevices(self):
+        """
+        Private method to load the list of unknown devices.
+        """
+        self.deviceList.clear()
+        
+        devices = Preferences.getMicroPython("ManualDevices")
+        for device in devices:
+            itm = QListWidgetItem(
+                self.tr("{0} (0x{1:04x}/0x{2:04x})", "description, VID, PID")
+                .format(device["description"], device["vid"], device["pid"]),
+                self.deviceList)
+            itm.setData(self.DeviceDataRole, device)
+            itm.setData(self.ModifiedRole, False)
+        
+        self.__initialDeviceCount = self.deviceList.count()
+        
+        self.__checkButtons()
+    
+    def __isDirty(self):
+        """
+        Private method to check, if the dialog contains unsaved data.
+        
+        @return flag indicating the presence of unsaved data
+        @rtype bool
+        """
+        dirty = False
+        for row in range(self.deviceList.count()):
+            dirty |= self.deviceList.item(row).data(self.ModifiedRole)
+        dirty |= self.deviceList.count() != self.__initialDeviceCount
+        return dirty
+    
+    def __editItem(self, item):
+        """
+        Private method to edit the given item.
+        
+        @param item reference to the item to be edited
+        @type QListWidgetItem
+        """
+        if item is None:
+            # play it safe
+            return
+        
+        from .AddEditDevicesDialog import AddEditDevicesDialog
+        dlg = AddEditDevicesDialog(deviceData=item.data(self.DeviceDataRole))
+        if dlg.exec() == QDialog.Accepted:
+            deviceDict = dlg.getDeviceDict()
+            item.setData(self.DeviceDataRole, deviceDict)
+            item.setData(self.ModifiedRole, True)
+            
+            item.setText(self.tr("{0} (*)", "list entry is modified")
+                         .format(item.text()))
+    
+    def __saveDeviceData(self):
+        """
+        Private method to save the device data.
+        """
+        devices = []
+        
+        for row in range(self.deviceList.count()):
+            devices.append(self.deviceList.item(row).data(
+                self.DeviceDataRole))
+        Preferences.setMicroPython("ManualDevices", devices)
+        
+        return True
+    
+    @pyqtSlot()
+    def __checkButtons(self):
+        """
+        Private slot to set the enabled state of the buttons.
+        """
+        selectedItemsCount = len(self.deviceList.selectedItems())
+        self.editButton.setEnabled(selectedItemsCount == 1)
+        self.deleteButton.setEnabled(selectedItemsCount >= 1)
+    
+    @pyqtSlot(QListWidgetItem)
+    def on_deviceList_itemActivated(self, item):
+        """
+        Private slot to edit the data of the activated item.
+        
+        @param item reference to the activated item
+        @type QListWidgetItem
+        """
+        self.__editItem(item)
+    
+    @pyqtSlot()
+    def on_deviceList_itemSelectionChanged(self):
+        """
+        Private slot to handle a change of selected items.
+        """
+        self.__checkButtons()
+    
+    @pyqtSlot()
+    def on_editButton_clicked(self):
+        """
+        Private slot to edit the selected item.
+        """
+        itm = self.deviceList.selectedItems()[0]
+        self.__editItem(itm)
+    
+    @pyqtSlot()
+    def on_deleteButton_clicked(self):
+        """
+        Private slot to delete the selected entries.
+        """
+        unsaved = False
+        for itm in self.deviceList.selectedItems():
+            unsaved |= itm.data(self.ModifiedRole)
+        if unsaved:
+            ok = E5MessageBox.yesNo(
+                self,
+                self.tr("Delete Unknown Devices"),
+                self.tr("The selected entries contain some with modified"
+                        " data. Shall they really be deleted?"))
+            if not ok:
+                return
+        
+        for itm in self.deviceList.selectedItems():
+            self.deviceList.takeItem(self.deviceList.row(itm))
+            del itm
+    
+    @pyqtSlot()
+    def on_deleteAllButton_clicked(self):
+        """
+        Private slot to delete all devices.
+        """
+        if self.__isDirty():
+            ok = E5MessageBox.yesNo(
+                self,
+                self.tr("Delete Unknown Devices"),
+                self.tr("The list contains some devices with modified"
+                        " data. Shall they really be deleted?"))
+            if not ok:
+                return
+            
+        self.deviceList.clear()
+    
+    @pyqtSlot()
+    def on_restoreButton_clicked(self):
+        """
+        Private slot to restore the list of unknown devices.
+        """
+        if self.__isDirty():
+            ok = E5MessageBox.yesNo(
+                self,
+                self.tr("Restore Unknown Devices"),
+                self.tr("Restoring the list of unknown devices will overwrite"
+                        " all changes made. Do you really want to restore the"
+                        " list?"))
+            if not ok:
+                return
+        
+        self.__loadDevices()
+    
+    @pyqtSlot()
+    def on_reportButton_clicked(self):
+        """
+        Private slot to report the data of all boards to the eric-bugs email
+        address.
+        """
+        if self.deviceList.count() > 0:
+            bodyList = [
+                "These are my MicroPython devices not yet known by eric."
+                " Please add them.",
+                "",
+            ]
+            
+            for row in range(self.deviceList.count()):
+                deviceDict = self.deviceList.item(row).data(
+                    self.DeviceDataRole)
+                bodyList += [
+                    "Board #{0}:".format(row),
+                    "  VID: {0}".format(deviceDict["vid"]),
+                    "  PID: {0}".format(deviceDict["pid"]),
+                    "  Description: {0}".format(deviceDict["description"]),
+                    "  Device Type: {0}".format(deviceDict["type"]),
+                    "  Data Volume: {0}".format(deviceDict["data_volume"]),
+                    "  Flash Volume: {0}".format(deviceDict["flash_volume"]),
+                    ""
+                ]
+            
+            urlQuery = QUrlQuery()
+            urlQuery.addQueryItem("subject", "Unsupported MicroPython Devices")
+            urlQuery.addQueryItem("body", "\r\n".join(bodyList))
+            
+            url = QUrl("mailto:{0}".format(BugAddress))
+            url.setQuery(urlQuery)
+            
+            QDesktopServices.openUrl(url)
+    
+    @pyqtSlot()
+    def on_buttonBox_accepted(self):
+        """
+        Private slot to handle the OK button press.
+        
+        This action saves the edited list to the preferences store.
+        """
+        self.__saveDeviceData()
+        self.accept()
+    
+    @pyqtSlot()
+    def on_buttonBox_rejected(self):
+        """
+        Private slot handling the cancellation of the dialog.
+        """
+        if self.__isDirty():
+            ok = E5MessageBox.okToClearData(
+                self,
+                self.tr("Unsaved Data"),
+                self.tr("""The list of devices contains some with modified"""
+                        """ data."""),
+                self.__saveDeviceData)
+            if not ok:
+                return
+        
+        self.reject()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/MicroPython/UnknownDevicesDialog.ui	Sat Feb 06 19:17:25 2021 +0100
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>UnknownDevicesDialog</class>
+ <widget class="QDialog" name="UnknownDevicesDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>450</width>
+    <height>500</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Unknown Devices</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QListWidget" name="deviceList">
+     <property name="alternatingRowColors">
+      <bool>true</bool>
+     </property>
+     <property name="selectionMode">
+      <enum>QAbstractItemView::ExtendedSelection</enum>
+     </property>
+     <property name="sortingEnabled">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <layout class="QVBoxLayout" name="verticalLayout">
+     <item>
+      <widget class="QPushButton" name="editButton">
+       <property name="toolTip">
+        <string>Press to edit the selected entry</string>
+       </property>
+       <property name="text">
+        <string>Edit...</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="Line" name="line">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="deleteButton">
+       <property name="toolTip">
+        <string>Press to delete the selected entries</string>
+       </property>
+       <property name="text">
+        <string>Delete</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="deleteAllButton">
+       <property name="toolTip">
+        <string>Press to delete all entries</string>
+       </property>
+       <property name="text">
+        <string>Delete All</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="verticalSpacer">
+       <property name="orientation">
+        <enum>Qt::Vertical</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>20</width>
+         <height>128</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="restoreButton">
+       <property name="toolTip">
+        <string>Press to restore the list of devices</string>
+       </property>
+       <property name="text">
+        <string>Restore</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item row="2" column="0" colspan="2">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0" colspan="2">
+    <widget class="QPushButton" name="reportButton">
+     <property name="toolTip">
+      <string>Press to report the data of all boards via email</string>
+     </property>
+     <property name="text">
+      <string>Report All Data</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>deviceList</tabstop>
+  <tabstop>editButton</tabstop>
+  <tabstop>deleteButton</tabstop>
+  <tabstop>deleteAllButton</tabstop>
+  <tabstop>restoreButton</tabstop>
+  <tabstop>reportButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>

eric ide

mercurial