Tue, 19 Mar 2024 16:36:16 +0100
Fixed a 'semver' compatibility issue in the CircuitPython updater and the MIP package dialog.
9740 | 1 | # -*- coding: utf-8 -*- |
2 | ||
10439
21c28b0f9e41
Updated copyright for 2024.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
9768
diff
changeset
|
3 | # Copyright (c) 2023 - 2024 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 | ||
52 | self.__modules = { | |
53 | m.name: m | |
54 | for m in circup.find_modules(devicePath, circup.get_bundles_list()) | |
55 | if m.outofdate | |
56 | } | |
57 | if self.__modules: | |
58 | self.header.setText( | |
59 | self.tr( | |
60 | "The following modules are out of date or probably need an update." | |
61 | "\nMajor Updates may include breaking changes. Review before" | |
62 | " updating.\nMPY Format changes require an update." | |
63 | ) | |
64 | ) | |
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
|
65 | 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
|
66 | 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
|
67 | 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
|
68 | versionIsValid = VersionInfo.isvalid |
9740 | 69 | 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
|
70 | if isinstance(module.bundle_version, str) and not versionIsValid( |
9740 | 71 | module.bundle_version |
72 | ): | |
73 | reason = self.tr("Incorrect '__version__' Metadata") | |
74 | needsUpdate = True | |
75 | elif module.bad_format: | |
76 | reason = self.tr("Corrupted or Unknown MPY Format") | |
77 | needsUpdate = True | |
78 | elif module.mpy_mismatch: | |
79 | reason = self.tr("MPY Format") | |
80 | needsUpdate = True | |
81 | elif module.major_update: | |
82 | reason = self.tr("Major Version") | |
83 | needsUpdate = False | |
84 | else: | |
85 | reason = self.tr("Minor Version") | |
86 | needsUpdate = False | |
87 | itm = QTreeWidgetItem( | |
88 | self.modulesList, | |
89 | [ | |
90 | module.name, | |
10621
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
91 | ( |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
92 | module.device_version |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
93 | if module.device_version |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
94 | else self.tr("unknown") |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
95 | ), |
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 | module.bundle_version |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
98 | if module.bundle_version |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
99 | else self.tr("unknown") |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
100 | ), |
9740 | 101 | reason, |
102 | ], | |
103 | ) | |
104 | if self.__selectionMode: | |
105 | itm.setFlags(itm.flags() | Qt.ItemFlag.ItemIsUserCheckable) | |
106 | itm.setCheckState( | |
107 | 0, | |
10621
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
108 | ( |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
109 | Qt.CheckState.Checked |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
110 | if needsUpdate |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
111 | else Qt.CheckState.Unchecked |
f5631f40c4d9
Corrected some code formatting issues.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
112 | ), |
9740 | 113 | ) |
114 | if needsUpdate: | |
115 | self.__checkCount += 1 | |
116 | else: | |
117 | self.header.setText(self.tr("All modules are up-to-date.")) | |
118 | ||
119 | self.modulesList.sortItems(0, Qt.SortOrder.AscendingOrder) | |
120 | for column in range(self.modulesList.columnCount()): | |
121 | self.modulesList.resizeColumnToContents(column) | |
122 | ||
123 | self.__checkCountUpdated() | |
124 | ||
125 | @pyqtSlot(QTreeWidgetItem, int) | |
126 | def on_modulesList_itemChanged(self, item, column): | |
127 | """ | |
128 | Private slot to handle a change of the check state of an item. | |
129 | ||
130 | @param item reference to the changed item | |
131 | @type QTreeWidgetItem | |
132 | @param column changed column | |
133 | @type int | |
134 | """ | |
135 | if self.__selectionMode: | |
136 | if item.checkState(0) == Qt.CheckState.Checked: | |
137 | 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
|
138 | elif self.__checkCount > 0: |
9740 | 139 | self.__checkCount -= 1 |
140 | ||
141 | self.__checkCountUpdated() | |
142 | ||
143 | def __checkCountUpdated(self): | |
144 | """ | |
145 | Private method to handle an update of the check count. | |
146 | """ | |
147 | if self.__selectionMode: | |
148 | self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled( | |
149 | self.__checkCount > 0 | |
150 | ) | |
151 | ||
152 | def getSelection(self): | |
153 | """ | |
154 | Public method to get the list of selected modules. | |
155 | ||
156 | @return list of selected modules | |
157 | @rtype circup.Module | |
158 | """ | |
159 | results = [] | |
160 | if self.__selectionMode: | |
161 | for row in range(self.modulesList.topLevelItemCount()): | |
162 | itm = self.modulesList.topLevelItem(row) | |
163 | if itm.checkState(0) == Qt.CheckState.Checked: | |
164 | results.append(self.__modules[itm.text(0)]) | |
165 | ||
166 | return results |