48 @param parent reference to the parent widget (defaults to None) |
50 @param parent reference to the parent widget (defaults to None) |
49 @type QWidget (optional) |
51 @type QWidget (optional) |
50 """ |
52 """ |
51 super().__init__(parent) |
53 super().__init__(parent) |
52 self.setupUi(self) |
54 self.setupUi(self) |
53 |
55 |
54 self.__pip = pip |
56 self.__pip = pip |
55 self.__environment = environment |
57 self.__environment = environment |
56 |
58 |
57 self.__allFilter = self.tr("<All>") |
59 self.__allFilter = self.tr("<All>") |
58 |
60 |
59 self.__saveCSVButton = self.buttonBox.addButton( |
61 self.__saveCSVButton = self.buttonBox.addButton( |
60 self.tr("Save as CSV..."), QDialogButtonBox.ButtonRole.ActionRole) |
62 self.tr("Save as CSV..."), QDialogButtonBox.ButtonRole.ActionRole |
|
63 ) |
61 self.__saveCSVButton.clicked.connect(self.__saveAsCSV) |
64 self.__saveCSVButton.clicked.connect(self.__saveAsCSV) |
62 |
65 |
63 self.buttonBox.button( |
66 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setDefault(True) |
64 QDialogButtonBox.StandardButton.Close).setDefault(True) |
67 |
65 |
|
66 self.localCheckBox.setChecked(localPackages) |
68 self.localCheckBox.setChecked(localPackages) |
67 self.userCheckBox.setChecked(usersite) |
69 self.userCheckBox.setChecked(usersite) |
68 |
70 |
69 self.localCheckBox.toggled.connect(self.__refreshLicenses) |
71 self.localCheckBox.toggled.connect(self.__refreshLicenses) |
70 self.userCheckBox.toggled.connect(self.__refreshLicenses) |
72 self.userCheckBox.toggled.connect(self.__refreshLicenses) |
71 |
73 |
72 if environment: |
74 if environment: |
73 self.environmentLabel.setText("<b>{0}</b>".format( |
75 self.environmentLabel.setText( |
74 self.tr('Licenses of "{0}"').format(environment) |
76 "<b>{0}</b>".format(self.tr('Licenses of "{0}"').format(environment)) |
75 )) |
77 ) |
76 else: |
78 else: |
77 # That should never happen; play it safe. |
79 # That should never happen; play it safe. |
78 self.environmentLabel.setText(self.tr("No environment specified.")) |
80 self.environmentLabel.setText(self.tr("No environment specified.")) |
79 |
81 |
80 self.licenseFilterComboBox.currentTextChanged.connect( |
82 self.licenseFilterComboBox.currentTextChanged.connect( |
81 self.__filterPackagesByLicense) |
83 self.__filterPackagesByLicense |
82 |
84 ) |
|
85 |
83 self.__refreshLicenses() |
86 self.__refreshLicenses() |
84 |
87 |
85 @pyqtSlot() |
88 @pyqtSlot() |
86 def __refreshLicenses(self): |
89 def __refreshLicenses(self): |
87 """ |
90 """ |
88 Private slot to refresh the license lists. |
91 Private slot to refresh the license lists. |
89 """ |
92 """ |
90 with EricOverrideCursor(): |
93 with EricOverrideCursor(): |
91 self.licensesList.clear() |
94 self.licensesList.clear() |
92 self.summaryList.clear() |
95 self.summaryList.clear() |
93 self.licenseFilterComboBox.clear() |
96 self.licenseFilterComboBox.clear() |
94 |
97 |
95 licensesForFilter = set() |
98 licensesForFilter = set() |
96 |
99 |
97 # step 1: show the licenses per package |
100 # step 1: show the licenses per package |
98 self.licensesList.setUpdatesEnabled(False) |
101 self.licensesList.setUpdatesEnabled(False) |
99 licenses = self.__pip.getLicenses( |
102 licenses = self.__pip.getLicenses( |
100 self.__environment, |
103 self.__environment, |
101 localPackages=self.localCheckBox.isChecked(), |
104 localPackages=self.localCheckBox.isChecked(), |
102 usersite=self.userCheckBox.isChecked(), |
105 usersite=self.userCheckBox.isChecked(), |
103 ) |
106 ) |
104 for lic in licenses: |
107 for lic in licenses: |
105 QTreeWidgetItem(self.licensesList, [ |
108 QTreeWidgetItem( |
106 lic["Name"], |
109 self.licensesList, |
107 lic["Version"], |
110 [ |
108 lic["License"].replace("; ", "\n"), |
111 lic["Name"], |
109 ]) |
112 lic["Version"], |
110 |
113 lic["License"].replace("; ", "\n"), |
|
114 ], |
|
115 ) |
|
116 |
111 self.licensesList.sortItems( |
117 self.licensesList.sortItems( |
112 PipLicensesDialog.LicensesPackageColumn, |
118 PipLicensesDialog.LicensesPackageColumn, Qt.SortOrder.AscendingOrder |
113 Qt.SortOrder.AscendingOrder) |
119 ) |
114 for col in range(self.licensesList.columnCount()): |
120 for col in range(self.licensesList.columnCount()): |
115 self.licensesList.resizeColumnToContents(col) |
121 self.licensesList.resizeColumnToContents(col) |
116 self.licensesList.setUpdatesEnabled(True) |
122 self.licensesList.setUpdatesEnabled(True) |
117 |
123 |
118 # step 2: show the licenses summary |
124 # step 2: show the licenses summary |
119 self.summaryList.setUpdatesEnabled(False) |
125 self.summaryList.setUpdatesEnabled(False) |
120 licenses = self.__pip.getLicensesSummary( |
126 licenses = self.__pip.getLicensesSummary( |
121 self.__environment, |
127 self.__environment, |
122 localPackages=self.localCheckBox.isChecked(), |
128 localPackages=self.localCheckBox.isChecked(), |
123 usersite=self.userCheckBox.isChecked(), |
129 usersite=self.userCheckBox.isChecked(), |
124 ) |
130 ) |
125 for lic in licenses: |
131 for lic in licenses: |
126 QTreeWidgetItem(self.summaryList, [ |
132 QTreeWidgetItem( |
127 "{0:4d}".format(lic["Count"]), |
133 self.summaryList, |
128 lic["License"].replace("; ", "\n"), |
134 [ |
129 ]) |
135 "{0:4d}".format(lic["Count"]), |
|
136 lic["License"].replace("; ", "\n"), |
|
137 ], |
|
138 ) |
130 licensesForFilter |= set(lic["License"].split("; ")) |
139 licensesForFilter |= set(lic["License"].split("; ")) |
131 |
140 |
132 self.summaryList.sortItems( |
141 self.summaryList.sortItems( |
133 PipLicensesDialog.SummaryLicenseColumn, |
142 PipLicensesDialog.SummaryLicenseColumn, Qt.SortOrder.AscendingOrder |
134 Qt.SortOrder.AscendingOrder) |
143 ) |
135 for col in range(self.summaryList.columnCount()): |
144 for col in range(self.summaryList.columnCount()): |
136 self.summaryList.resizeColumnToContents(col) |
145 self.summaryList.resizeColumnToContents(col) |
137 self.summaryList.setUpdatesEnabled(True) |
146 self.summaryList.setUpdatesEnabled(True) |
138 |
147 |
139 self.licenseFilterComboBox.addItems( |
148 self.licenseFilterComboBox.addItems( |
140 [self.__allFilter] + sorted(licensesForFilter)) |
149 [self.__allFilter] + sorted(licensesForFilter) |
141 |
150 ) |
|
151 |
142 enable = bool(self.licensesList.topLevelItemCount()) |
152 enable = bool(self.licensesList.topLevelItemCount()) |
143 self.__saveCSVButton.setEnabled(enable) |
153 self.__saveCSVButton.setEnabled(enable) |
144 |
154 |
145 @pyqtSlot(str) |
155 @pyqtSlot(str) |
146 def __filterPackagesByLicense(self, licenseName): |
156 def __filterPackagesByLicense(self, licenseName): |
147 """ |
157 """ |
148 Private slot to filter the list of packages by license. |
158 Private slot to filter the list of packages by license. |
149 |
159 |
150 @param licenseName license name |
160 @param licenseName license name |
151 @type str |
161 @type str |
152 """ |
162 """ |
153 pattern = r"\b{0}".format(re.escape(licenseName)) |
163 pattern = r"\b{0}".format(re.escape(licenseName)) |
154 if not licenseName.endswith((")", "]", "}")): |
164 if not licenseName.endswith((")", "]", "}")): |
158 itm = self.licensesList.topLevelItem(row) |
168 itm = self.licensesList.topLevelItem(row) |
159 if licenseName == self.__allFilter: |
169 if licenseName == self.__allFilter: |
160 itm.setHidden(False) |
170 itm.setHidden(False) |
161 else: |
171 else: |
162 itm.setHidden( |
172 itm.setHidden( |
163 regexp.search( |
173 regexp.search(itm.text(PipLicensesDialog.LicensesLicenseColumn)) |
164 itm.text(PipLicensesDialog.LicensesLicenseColumn) |
174 is None |
165 ) is None |
175 ) |
166 ) |
176 |
167 |
|
168 @pyqtSlot() |
177 @pyqtSlot() |
169 def __saveAsCSV(self): |
178 def __saveAsCSV(self): |
170 """ |
179 """ |
171 Private slot to save the license information as a CSV file. |
180 Private slot to save the license information as a CSV file. |
172 """ |
181 """ |
173 import csv |
182 import csv |
174 |
183 |
175 fileName, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( |
184 fileName, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( |
176 self, |
185 self, |
177 self.tr("Save as CSV"), |
186 self.tr("Save as CSV"), |
178 os.path.expanduser("~"), |
187 os.path.expanduser("~"), |
179 self.tr("CSV Files (*.csv);;All Files (*)"), |
188 self.tr("CSV Files (*.csv);;All Files (*)"), |
180 None, |
189 None, |
181 EricFileDialog.DontConfirmOverwrite |
190 EricFileDialog.DontConfirmOverwrite, |
182 ) |
191 ) |
183 if fileName: |
192 if fileName: |
184 ext = os.path.splitext(fileName)[1] |
193 ext = os.path.splitext(fileName)[1] |
185 if not ext: |
194 if not ext: |
186 ex = selectedFilter.split("(*")[1].split(")")[0] |
195 ex = selectedFilter.split("(*")[1].split(")")[0] |
187 if ex: |
196 if ex: |
188 fileName += ex |
197 fileName += ex |
189 |
198 |
190 try: |
199 try: |
191 with open(fileName, "w", newline="", |
200 with open(fileName, "w", newline="", encoding="utf-8") as csvFile: |
192 encoding="utf-8") as csvFile: |
|
193 fieldNames = ["Name", "Version", "License"] |
201 fieldNames = ["Name", "Version", "License"] |
194 writer = csv.DictWriter(csvFile, fieldnames=fieldNames) |
202 writer = csv.DictWriter(csvFile, fieldnames=fieldNames) |
195 |
203 |
196 writer.writeheader() |
204 writer.writeheader() |
197 for row in range(self.licensesList.topLevelItemCount()): |
205 for row in range(self.licensesList.topLevelItemCount()): |
198 itm = self.licensesList.topLevelItem(row) |
206 itm = self.licensesList.topLevelItem(row) |
199 writer.writerow({ |
207 writer.writerow( |
200 "Name": itm.text(0), |
208 { |
201 "Version": itm.text(1), |
209 "Name": itm.text(0), |
202 "License": itm.text(2), |
210 "Version": itm.text(1), |
203 }) |
211 "License": itm.text(2), |
|
212 } |
|
213 ) |
204 except OSError as err: |
214 except OSError as err: |
205 EricMessageBox.critical( |
215 EricMessageBox.critical( |
206 self, |
216 self, |
207 self.tr("Save as CSV"), |
217 self.tr("Save as CSV"), |
208 self.tr( |
218 self.tr( |
209 """<p>The license information could not be saved""" |
219 """<p>The license information could not be saved""" |
210 """ into the CSV file <b>{0}</b>.</p>""" |
220 """ into the CSV file <b>{0}</b>.</p>""" |
211 """<p>Reason: {1}</p>""" |
221 """<p>Reason: {1}</p>""" |
212 ).format(fileName, str(err)) |
222 ).format(fileName, str(err)), |
213 ) |
223 ) |