Sun, 16 Mar 2025 12:53:12 +0100
Added the Adafruit Feather nRF52840 to the list of known NRF52 boards and changed the list of known CircuitPython boards to be more explicit with respect to Adafruit boards (i.e. VID 0x239A).
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 |