Sat, 15 Mar 2025 11:53:21 +0100
MicroPython
- Added support for NRF52 based devices which support the UF2 standard.
9740 | 1 | # -*- coding: utf-8 -*- |
2 | ||
11090
f5f5f5803935
Updated copyright for 2025.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11011
diff
changeset
|
3 | # Copyright (c) 2023 - 2025 Detlev Offenbach <detlev@die-offenbachs.de> |
9740 | 4 | # |
5 | ||
6 | """ | |
7 | Module implementing a dialog to show outdated modules of a connected device. | |
8 | """ | |
9 | ||
10 | import circup | |
11 | ||
12 | from PyQt6.QtCore import Qt, pyqtSlot | |
13 | from PyQt6.QtWidgets import QDialog, QDialogButtonBox, QTreeWidgetItem | |
14 | from semver import VersionInfo | |
15 | ||
16 | from .Ui_ShowOutdatedDialog import Ui_ShowOutdatedDialog | |
17 | ||
18 | ||
19 | class ShowOutdatedDialog(QDialog, Ui_ShowOutdatedDialog): | |
20 | """ | |
21 | Class implementing a dialog to show outdated modules of a connected device. | |
22 | """ | |
23 | ||
24 | def __init__(self, devicePath, selectionMode=False, parent=None): | |
25 | """ | |
26 | Constructor | |
27 | ||
28 | @param devicePath path to the connected board | |
29 | @type str | |
30 | @param selectionMode flag indicating the activation of the selection mode | |
31 | (defaults to False) | |
32 | @type bool (optional) | |
33 | @param parent reference to the parent widget (defaults to None) | |
34 | @type QWidget (optional) | |
35 | """ | |
36 | super().__init__(parent) | |
37 | self.setupUi(self) | |
38 | ||
39 | self.header.clear() | |
40 | self.modulesList.clear() | |
41 | ||
42 | self.__checkCount = 0 | |
43 | self.__selectionMode = selectionMode | |
44 | if self.__selectionMode: | |
45 | self.buttonBox.setStandardButtons( | |
46 | QDialogButtonBox.StandardButton.Ok | |
47 | | QDialogButtonBox.StandardButton.Cancel | |
48 | ) | |
49 | else: | |
50 | self.buttonBox.setStandardButtons(QDialogButtonBox.StandardButton.Close) | |
51 | ||
10900 | 52 | backend = circup.DiskBackend(devicePath, circup.logger) |
9740 | 53 | self.__modules = { |
54 | m.name: m | |
10900 | 55 | for m in circup.find_modules(backend, circup.get_bundles_list()) |
9740 | 56 | if m.outofdate |
57 | } | |
58 | if self.__modules: | |
59 | self.header.setText( | |
60 | self.tr( | |
61 | "The following modules are out of date or probably need an update." | |
62 | "\nMajor Updates may include breaking changes. Review before" | |
63 | " updating.\nMPY Format changes require an update." | |
64 | ) | |
65 | ) | |
10643
08682797bfcd
Fixed a 'semver' compatibility issue in the CircuitPython updater and the MIP package dialog.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10621
diff
changeset
|
66 | try: |
08682797bfcd
Fixed a 'semver' compatibility issue in the CircuitPython updater and the MIP package dialog.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10621
diff
changeset
|
67 | versionIsValid = VersionInfo.is_valid |
08682797bfcd
Fixed a 'semver' compatibility issue in the CircuitPython updater and the MIP package dialog.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10621
diff
changeset
|
68 | except AttributeError: |
08682797bfcd
Fixed a 'semver' compatibility issue in the CircuitPython updater and the MIP package dialog.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10621
diff
changeset
|
69 | versionIsValid = VersionInfo.isvalid |
9740 | 70 | for module in self.__modules.values(): |
10643
08682797bfcd
Fixed a 'semver' compatibility issue in the CircuitPython updater and the MIP package dialog.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10621
diff
changeset
|
71 | if isinstance(module.bundle_version, str) and not versionIsValid( |
9740 | 72 | module.bundle_version |
73 | ): | |
74 | reason = self.tr("Incorrect '__version__' Metadata") | |
75 | needsUpdate = True | |
76 | elif module.bad_format: | |
77 | reason = self.tr("Corrupted or Unknown MPY Format") | |
78 | needsUpdate = True | |
79 | elif module.mpy_mismatch: | |
80 | reason = self.tr("MPY Format") | |
81 | needsUpdate = True | |
82 | elif module.major_update: | |
83 | reason = self.tr("Major Version") | |
84 | needsUpdate = False | |
85 | else: | |
86 | reason = self.tr("Minor Version") | |
87 | needsUpdate = False | |
88 | itm = QTreeWidgetItem( | |
89 | self.modulesList, | |
90 | [ | |
91 | module.name, | |
10621
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
92 | ( |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
93 | module.device_version |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
94 | if module.device_version |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
95 | else self.tr("unknown") |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
96 | ), |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
97 | ( |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
98 | module.bundle_version |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
99 | if module.bundle_version |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
100 | else self.tr("unknown") |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
101 | ), |
9740 | 102 | reason, |
103 | ], | |
104 | ) | |
105 | if self.__selectionMode: | |
106 | itm.setFlags(itm.flags() | Qt.ItemFlag.ItemIsUserCheckable) | |
107 | itm.setCheckState( | |
108 | 0, | |
10621
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
109 | ( |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
110 | Qt.CheckState.Checked |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
111 | if needsUpdate |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
112 | else Qt.CheckState.Unchecked |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
113 | ), |
9740 | 114 | ) |
115 | if needsUpdate: | |
116 | self.__checkCount += 1 | |
117 | else: | |
118 | self.header.setText(self.tr("All modules are up-to-date.")) | |
119 | ||
120 | self.modulesList.sortItems(0, Qt.SortOrder.AscendingOrder) | |
121 | for column in range(self.modulesList.columnCount()): | |
122 | self.modulesList.resizeColumnToContents(column) | |
123 | ||
124 | self.__checkCountUpdated() | |
125 | ||
126 | @pyqtSlot(QTreeWidgetItem, int) | |
127 | def on_modulesList_itemChanged(self, item, column): | |
128 | """ | |
129 | Private slot to handle a change of the check state of an item. | |
130 | ||
131 | @param item reference to the changed item | |
132 | @type QTreeWidgetItem | |
133 | @param column changed column | |
134 | @type int | |
135 | """ | |
136 | if self.__selectionMode: | |
137 | if item.checkState(0) == Qt.CheckState.Checked: | |
138 | self.__checkCount += 1 | |
9768
e2b622afb5ff
Fixed an issue causing the selection count of checkable selection lists going negative.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9756
diff
changeset
|
139 | elif self.__checkCount > 0: |
9740 | 140 | self.__checkCount -= 1 |
141 | ||
142 | self.__checkCountUpdated() | |
143 | ||
144 | def __checkCountUpdated(self): | |
145 | """ | |
146 | Private method to handle an update of the check count. | |
147 | """ | |
148 | if self.__selectionMode: | |
149 | self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled( | |
150 | self.__checkCount > 0 | |
151 | ) | |
152 | ||
153 | def getSelection(self): | |
154 | """ | |
155 | Public method to get the list of selected modules. | |
156 | ||
157 | @return list of selected modules | |
11011
f1f1c8d0255d
Modified the CircuitPython library management for circup >= 2.0.0.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10900
diff
changeset
|
158 | @rtype circup.module.Module |
9740 | 159 | """ |
160 | results = [] | |
161 | if self.__selectionMode: | |
162 | for row in range(self.modulesList.topLevelItemCount()): | |
163 | itm = self.modulesList.topLevelItem(row) | |
164 | if itm.checkState(0) == Qt.CheckState.Checked: | |
165 | results.append(self.__modules[itm.text(0)]) | |
166 | ||
167 | return results |