eric7/MicroPython/UnknownDevicesDialog.py

Sat, 08 Jan 2022 20:12:37 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 08 Jan 2022 20:12:37 +0100
branch
eric7
changeset 8910
02d67de5ec1c
parent 8881
54e42bc2437a
permissions
-rw-r--r--

MicroPython
- updated the list of known CircuitPython boards

# -*- coding: utf-8 -*-

# Copyright (c) 2021 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing a dialog to manage the list of unknown devices.
"""

from PyQt6.QtCore import pyqtSlot, Qt, QUrl, QUrlQuery
from PyQt6.QtGui import QDesktopServices
from PyQt6.QtWidgets import QDialog, QListWidgetItem

from EricWidgets import EricMessageBox

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.ItemDataRole.UserRole
    ModifiedRole = Qt.ItemDataRole.UserRole + 1
    
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget (defaults to None)
        @type QWidget (optional)
        """
        super().__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.DialogCode.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.
        
        @return flag indicating a successful save
        @rtype bool
        """
        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 = EricMessageBox.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 = EricMessageBox.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 = EricMessageBox.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 = EricMessageBox.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()

eric ide

mercurial