26 |
30 |
27 class RawMetricsDialog(QDialog, Ui_RawMetricsDialog): |
31 class RawMetricsDialog(QDialog, Ui_RawMetricsDialog): |
28 """ |
32 """ |
29 Class implementing a dialog to show raw code metrics. |
33 Class implementing a dialog to show raw code metrics. |
30 """ |
34 """ |
|
35 |
31 FilePathRole = Qt.ItemDataRole.UserRole + 1 |
36 FilePathRole = Qt.ItemDataRole.UserRole + 1 |
32 |
37 |
33 def __init__(self, radonService, parent=None): |
38 def __init__(self, radonService, parent=None): |
34 """ |
39 """ |
35 Constructor |
40 Constructor |
36 |
41 |
37 @param radonService reference to the service |
42 @param radonService reference to the service |
38 @type RadonMetricsPlugin |
43 @type RadonMetricsPlugin |
39 @param parent reference to the parent widget |
44 @param parent reference to the parent widget |
40 @type QWidget |
45 @type QWidget |
41 """ |
46 """ |
42 super().__init__(parent) |
47 super().__init__(parent) |
43 self.setupUi(self) |
48 self.setupUi(self) |
44 self.setWindowFlags(Qt.WindowType.Window) |
49 self.setWindowFlags(Qt.WindowType.Window) |
45 |
50 |
46 self.buttonBox.button( |
51 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False) |
47 QDialogButtonBox.StandardButton.Close).setEnabled(False) |
52 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True) |
48 self.buttonBox.button( |
53 |
49 QDialogButtonBox.StandardButton.Cancel).setDefault(True) |
54 self.summaryList.headerItem().setText(self.summaryList.columnCount(), "") |
50 |
|
51 self.summaryList.headerItem().setText( |
|
52 self.summaryList.columnCount(), "") |
|
53 self.summaryList.header().resizeSection(0, 200) |
55 self.summaryList.header().resizeSection(0, 200) |
54 self.summaryList.header().resizeSection(1, 100) |
56 self.summaryList.header().resizeSection(1, 100) |
55 |
57 |
56 self.resultList.headerItem().setText(self.resultList.columnCount(), "") |
58 self.resultList.headerItem().setText(self.resultList.columnCount(), "") |
57 |
59 |
58 self.radonService = radonService |
60 self.radonService = radonService |
59 self.radonService.metricsDone.connect(self.__processResult) |
61 self.radonService.metricsDone.connect(self.__processResult) |
60 self.radonService.error.connect(self.__processError) |
62 self.radonService.error.connect(self.__processError) |
61 self.radonService.batchFinished.connect(self.__batchFinished) |
63 self.radonService.batchFinished.connect(self.__batchFinished) |
62 |
64 |
63 self.cancelled = False |
65 self.cancelled = False |
64 |
66 |
65 self.__project = ericApp().getObject("Project") |
67 self.__project = ericApp().getObject("Project") |
66 self.__locale = QLocale() |
68 self.__locale = QLocale() |
67 self.__finished = True |
69 self.__finished = True |
68 self.__errorItem = None |
70 self.__errorItem = None |
69 |
71 |
70 self.__fileList = [] |
72 self.__fileList = [] |
71 self.filterFrame.setVisible(False) |
73 self.filterFrame.setVisible(False) |
72 |
74 |
73 self.explanationLabel.setText(self.tr( |
75 self.explanationLabel.setText( |
74 "<table>" |
76 self.tr( |
75 "<tr><td><b>LOC</b></td>" |
77 "<table>" |
76 "<td>Lines of code</td></tr>" |
78 "<tr><td><b>LOC</b></td>" |
77 "<tr><td><b>SLOC</b></td><td>Source lines of code</td></tr>" |
79 "<td>Lines of code</td></tr>" |
78 "<tr><td><b>LLOC</b></td><td>Logical lines of code</td></tr>" |
80 "<tr><td><b>SLOC</b></td><td>Source lines of code</td></tr>" |
79 "<tr><td><b>Comments</b></td><td>Comment lines</td></tr>" |
81 "<tr><td><b>LLOC</b></td><td>Logical lines of code</td></tr>" |
80 "<tr><td><b>Empty Comments</b></td><td>Comment lines not" |
82 "<tr><td><b>Comments</b></td><td>Comment lines</td></tr>" |
81 " containing code</td></tr>" |
83 "<tr><td><b>Empty Comments</b></td><td>Comment lines not" |
82 "<tr><td><b>Multi</b></td>" |
84 " containing code</td></tr>" |
83 "<td>Lines in multi line strings</td></tr>" |
85 "<tr><td><b>Multi</b></td>" |
84 "<tr><td><b>Empty</b></td><td>Blank lines</td></tr>" |
86 "<td>Lines in multi line strings</td></tr>" |
85 "<tr><td colspan=2><b>Comment Statistics:</b></td</tr>" |
87 "<tr><td><b>Empty</b></td><td>Blank lines</td></tr>" |
86 "<tr><td><b>C % L</b></td><td>Comments to lines ratio</td></tr>" |
88 "<tr><td colspan=2><b>Comment Statistics:</b></td</tr>" |
87 "<tr><td><b>C % S</b></td>" |
89 "<tr><td><b>C % L</b></td><td>Comments to lines ratio</td></tr>" |
88 "<td>Comments to source lines ratio</td></tr>" |
90 "<tr><td><b>C % S</b></td>" |
89 "<tr><td><b>C + M % L</b></td>" |
91 "<td>Comments to source lines ratio</td></tr>" |
90 "<td>Comments plus multi line strings to lines ratio</td></tr>" |
92 "<tr><td><b>C + M % L</b></td>" |
91 "</table>" |
93 "<td>Comments plus multi line strings to lines ratio</td></tr>" |
92 )) |
94 "</table>" |
93 |
95 ) |
|
96 ) |
|
97 |
94 def __resizeResultColumns(self): |
98 def __resizeResultColumns(self): |
95 """ |
99 """ |
96 Private method to resize the list columns. |
100 Private method to resize the list columns. |
97 """ |
101 """ |
98 self.resultList.header().resizeSections( |
102 self.resultList.header().resizeSections(QHeaderView.ResizeMode.ResizeToContents) |
99 QHeaderView.ResizeMode.ResizeToContents) |
|
100 self.resultList.header().setStretchLastSection(True) |
103 self.resultList.header().setStretchLastSection(True) |
101 |
104 |
102 def __createResultItem(self, filename, values): |
105 def __createResultItem(self, filename, values): |
103 """ |
106 """ |
104 Private slot to create a new item in the result list. |
107 Private slot to create a new item in the result list. |
105 |
108 |
106 @param filename name of the file |
109 @param filename name of the file |
107 @type str |
110 @type str |
108 @param values values to be displayed |
111 @param values values to be displayed |
109 @type dict |
112 @type dict |
110 """ |
113 """ |
112 for value in self.__getValues(values): |
115 for value in self.__getValues(values): |
113 try: |
116 try: |
114 data.append("{0:5}".format(int(value))) |
117 data.append("{0:5}".format(int(value))) |
115 except ValueError: |
118 except ValueError: |
116 data.append(value) |
119 data.append(value) |
117 data.append("{0:3.0%}".format(min( |
120 data.append( |
118 values["comments"] / (float(values["loc"]) or 1), |
121 "{0:3.0%}".format( |
119 1.0))) |
122 min(values["comments"] / (float(values["loc"]) or 1), 1.0) |
120 data.append("{0:3.0%}".format(min( |
123 ) |
121 values["comments"] / (float(values["sloc"]) or 1), |
124 ) |
122 1.0))) |
125 data.append( |
123 data.append("{0:3.0%}".format(min( |
126 "{0:3.0%}".format( |
124 (values["comments"] + values["multi"]) / |
127 min(values["comments"] / (float(values["sloc"]) or 1), 1.0) |
125 (float(values["loc"]) or 1), |
128 ) |
126 1.0))) |
129 ) |
|
130 data.append( |
|
131 "{0:3.0%}".format( |
|
132 min( |
|
133 (values["comments"] + values["multi"]) |
|
134 / (float(values["loc"]) or 1), |
|
135 1.0, |
|
136 ) |
|
137 ) |
|
138 ) |
127 itm = QTreeWidgetItem(self.resultList, data) |
139 itm = QTreeWidgetItem(self.resultList, data) |
128 for col in range(1, 10): |
140 for col in range(1, 10): |
129 itm.setTextAlignment(col, Qt.AlignmentFlag.AlignRight) |
141 itm.setTextAlignment(col, Qt.AlignmentFlag.AlignRight) |
130 itm.setData(0, self.FilePathRole, filename) |
142 itm.setData(0, self.FilePathRole, filename) |
131 |
143 |
132 def __createErrorItem(self, filename, message): |
144 def __createErrorItem(self, filename, message): |
133 """ |
145 """ |
134 Private slot to create a new error item in the result list. |
146 Private slot to create a new error item in the result list. |
135 |
147 |
136 @param filename name of the file |
148 @param filename name of the file |
137 @type str |
149 @type str |
138 @param message error message |
150 @param message error message |
139 @type str |
151 @type str |
140 """ |
152 """ |
141 if self.__errorItem is None: |
153 if self.__errorItem is None: |
142 self.__errorItem = QTreeWidgetItem(self.resultList, [ |
154 self.__errorItem = QTreeWidgetItem(self.resultList, [self.tr("Errors")]) |
143 self.tr("Errors")]) |
|
144 self.__errorItem.setExpanded(True) |
155 self.__errorItem.setExpanded(True) |
145 self.__errorItem.setForeground(0, Qt.GlobalColor.red) |
156 self.__errorItem.setForeground(0, Qt.GlobalColor.red) |
146 |
157 |
147 msg = "{0} ({1})".format(self.__project.getRelativePath(filename), |
158 msg = "{0} ({1})".format(self.__project.getRelativePath(filename), message) |
148 message) |
|
149 if not self.resultList.findItems(msg, Qt.MatchFlag.MatchExactly): |
159 if not self.resultList.findItems(msg, Qt.MatchFlag.MatchExactly): |
150 itm = QTreeWidgetItem(self.__errorItem, [msg]) |
160 itm = QTreeWidgetItem(self.__errorItem, [msg]) |
151 itm.setForeground(0, Qt.GlobalColor.red) |
161 itm.setForeground(0, Qt.GlobalColor.red) |
152 itm.setFirstColumnSpanned(True) |
162 itm.setFirstColumnSpanned(True) |
153 |
163 |
154 def prepare(self, fileList, project): |
164 def prepare(self, fileList, project): |
155 """ |
165 """ |
156 Public method to prepare the dialog with a list of filenames. |
166 Public method to prepare the dialog with a list of filenames. |
157 |
167 |
158 @param fileList list of filenames |
168 @param fileList list of filenames |
159 @type list of str |
169 @type list of str |
160 @param project reference to the project object |
170 @param project reference to the project object |
161 @type Project |
171 @type Project |
162 """ |
172 """ |
163 self.__fileList = fileList[:] |
173 self.__fileList = fileList[:] |
164 self.__project = project |
174 self.__project = project |
165 |
175 |
166 self.buttonBox.button( |
176 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(True) |
167 QDialogButtonBox.StandardButton.Close).setEnabled(True) |
177 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(False) |
168 self.buttonBox.button( |
178 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setDefault(True) |
169 QDialogButtonBox.StandardButton.Cancel).setEnabled(False) |
179 |
170 self.buttonBox.button( |
|
171 QDialogButtonBox.StandardButton.Close).setDefault(True) |
|
172 |
|
173 self.filterFrame.setVisible(True) |
180 self.filterFrame.setVisible(True) |
174 |
181 |
175 self.__data = self.__project.getData( |
182 self.__data = self.__project.getData("OTHERTOOLSPARMS", "RadonCodeMetrics") |
176 "OTHERTOOLSPARMS", "RadonCodeMetrics") |
|
177 if self.__data is None or "ExcludeFiles" not in self.__data: |
183 if self.__data is None or "ExcludeFiles" not in self.__data: |
178 self.__data = {"ExcludeFiles": ""} |
184 self.__data = {"ExcludeFiles": ""} |
179 self.excludeFilesEdit.setText(self.__data["ExcludeFiles"]) |
185 self.excludeFilesEdit.setText(self.__data["ExcludeFiles"]) |
180 |
186 |
181 def start(self, fn): |
187 def start(self, fn): |
182 """ |
188 """ |
183 Public slot to start the code metrics determination. |
189 Public slot to start the code metrics determination. |
184 |
190 |
185 @param fn file or list of files or directory to show |
191 @param fn file or list of files or directory to show |
186 the code metrics for |
192 the code metrics for |
187 @type str or list of str |
193 @type str or list of str |
188 """ |
194 """ |
189 self.cancelled = False |
195 self.cancelled = False |
190 self.__errorItem = None |
196 self.__errorItem = None |
191 self.resultList.clear() |
197 self.resultList.clear() |
192 self.summaryList.clear() |
198 self.summaryList.clear() |
193 QApplication.processEvents() |
199 QApplication.processEvents() |
194 |
200 |
195 self.buttonBox.button( |
201 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False) |
196 QDialogButtonBox.StandardButton.Close).setEnabled(False) |
202 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(True) |
197 self.buttonBox.button( |
203 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True) |
198 QDialogButtonBox.StandardButton.Cancel).setEnabled(True) |
|
199 self.buttonBox.button( |
|
200 QDialogButtonBox.StandardButton.Cancel).setDefault(True) |
|
201 QApplication.processEvents() |
204 QApplication.processEvents() |
202 |
205 |
203 if isinstance(fn, list): |
206 if isinstance(fn, list): |
204 self.files = fn |
207 self.files = fn |
205 elif os.path.isdir(fn): |
208 elif os.path.isdir(fn): |
206 self.files = [] |
209 self.files = [] |
207 extensions = set(Preferences.getPython("Python3Extensions")) |
210 extensions = set(Preferences.getPython("Python3Extensions")) |
208 for ext in extensions: |
211 for ext in extensions: |
209 self.files.extend( |
212 self.files.extend(Utilities.direntries(fn, True, "*{0}".format(ext), 0)) |
210 Utilities.direntries(fn, True, '*{0}'.format(ext), 0)) |
|
211 else: |
213 else: |
212 self.files = [fn] |
214 self.files = [fn] |
213 self.files.sort() |
215 self.files.sort() |
214 # check for missing files |
216 # check for missing files |
215 for f in self.files[:]: |
217 for f in self.files[:]: |
216 if not os.path.exists(f): |
218 if not os.path.exists(f): |
217 self.files.remove(f) |
219 self.files.remove(f) |
218 |
220 |
219 self.__summary = {"files": 0} |
221 self.__summary = {"files": 0} |
220 for key in ['loc', 'lloc', 'sloc', 'comments', 'multi', |
222 for key in [ |
221 'single_comments', 'blank']: |
223 "loc", |
|
224 "lloc", |
|
225 "sloc", |
|
226 "comments", |
|
227 "multi", |
|
228 "single_comments", |
|
229 "blank", |
|
230 ]: |
222 self.__summary[key] = 0 |
231 self.__summary[key] = 0 |
223 |
232 |
224 if len(self.files) > 0: |
233 if len(self.files) > 0: |
225 # disable updates of the list for speed |
234 # disable updates of the list for speed |
226 self.resultList.setUpdatesEnabled(False) |
235 self.resultList.setUpdatesEnabled(False) |
227 self.resultList.setSortingEnabled(False) |
236 self.resultList.setSortingEnabled(False) |
228 |
237 |
229 self.checkProgress.setMaximum(len(self.files)) |
238 self.checkProgress.setMaximum(len(self.files)) |
230 self.checkProgress.setVisible(len(self.files) > 1) |
239 self.checkProgress.setVisible(len(self.files) > 1) |
231 QApplication.processEvents() |
240 QApplication.processEvents() |
232 |
241 |
233 # now go through all the files |
242 # now go through all the files |
234 self.progress = 0 |
243 self.progress = 0 |
235 if len(self.files) == 1: |
244 if len(self.files) == 1: |
236 self.__batch = False |
245 self.__batch = False |
237 self.rawMetrics() |
246 self.rawMetrics() |
238 else: |
247 else: |
239 self.__batch = True |
248 self.__batch = True |
240 self.rawMetricsBatch() |
249 self.rawMetricsBatch() |
241 |
250 |
242 def rawMetrics(self, codestring=''): |
251 def rawMetrics(self, codestring=""): |
243 """ |
252 """ |
244 Public method to start a code metrics calculation for one Python file. |
253 Public method to start a code metrics calculation for one Python file. |
245 |
254 |
246 The results are reported to the __processResult slot. |
255 The results are reported to the __processResult slot. |
247 |
256 |
248 @param codestring optional sourcestring |
257 @param codestring optional sourcestring |
249 @type str |
258 @type str |
250 """ |
259 """ |
251 if not self.files: |
260 if not self.files: |
252 self.checkProgress.setMaximum(1) |
261 self.checkProgress.setMaximum(1) |
253 self.checkProgress.setValue(1) |
262 self.checkProgress.setValue(1) |
254 self.__finish() |
263 self.__finish() |
255 return |
264 return |
256 |
265 |
257 self.filename = self.files.pop(0) |
266 self.filename = self.files.pop(0) |
258 self.checkProgress.setValue(self.progress) |
267 self.checkProgress.setValue(self.progress) |
259 QApplication.processEvents() |
268 QApplication.processEvents() |
260 |
269 |
261 if self.cancelled: |
270 if self.cancelled: |
262 return |
271 return |
263 |
272 |
264 try: |
273 try: |
265 self.source = Utilities.readEncodedFile(self.filename)[0] |
274 self.source = Utilities.readEncodedFile(self.filename)[0] |
266 self.source = Utilities.normalizeCode(self.source) |
275 self.source = Utilities.normalizeCode(self.source) |
267 except (UnicodeError, OSError) as msg: |
276 except (UnicodeError, OSError) as msg: |
268 self.__createErrorItem(self.filename, str(msg).rstrip()) |
277 self.__createErrorItem(self.filename, str(msg).rstrip()) |
270 # Continue with next file |
279 # Continue with next file |
271 self.rawMetrics() |
280 self.rawMetrics() |
272 return |
281 return |
273 |
282 |
274 self.__finished = False |
283 self.__finished = False |
275 self.radonService.rawMetrics( |
284 self.radonService.rawMetrics(None, self.filename, self.source) |
276 None, self.filename, self.source) |
|
277 |
285 |
278 def rawMetricsBatch(self): |
286 def rawMetricsBatch(self): |
279 """ |
287 """ |
280 Public method to start a code metrics calculation batch job. |
288 Public method to start a code metrics calculation batch job. |
281 |
289 |
282 The results are reported to the __processResult slot. |
290 The results are reported to the __processResult slot. |
283 """ |
291 """ |
284 self.__lastFileItem = None |
292 self.__lastFileItem = None |
285 |
293 |
286 argumentsList = [] |
294 argumentsList = [] |
287 for progress, filename in enumerate(self.files, start=1): |
295 for progress, filename in enumerate(self.files, start=1): |
288 self.checkProgress.setValue(progress) |
296 self.checkProgress.setValue(progress) |
289 QApplication.processEvents() |
297 QApplication.processEvents() |
290 |
298 |
291 try: |
299 try: |
292 source = Utilities.readEncodedFile(filename)[0] |
300 source = Utilities.readEncodedFile(filename)[0] |
293 source = Utilities.normalizeCode(source) |
301 source = Utilities.normalizeCode(source) |
294 except (UnicodeError, OSError) as msg: |
302 except (UnicodeError, OSError) as msg: |
295 self.__createErrorItem(filename, str(msg).rstrip()) |
303 self.__createErrorItem(filename, str(msg).rstrip()) |
296 continue |
304 continue |
297 |
305 |
298 argumentsList.append((filename, source)) |
306 argumentsList.append((filename, source)) |
299 |
307 |
300 # reset the progress bar to the checked files |
308 # reset the progress bar to the checked files |
301 self.checkProgress.setValue(self.progress) |
309 self.checkProgress.setValue(self.progress) |
302 QApplication.processEvents() |
310 QApplication.processEvents() |
303 |
311 |
304 self.__finished = False |
312 self.__finished = False |
305 self.radonService.rawMetricsBatch(argumentsList) |
313 self.radonService.rawMetricsBatch(argumentsList) |
306 |
314 |
307 def __batchFinished(self, type_): |
315 def __batchFinished(self, type_): |
308 """ |
316 """ |
309 Private slot handling the completion of a batch job. |
317 Private slot handling the completion of a batch job. |
310 |
318 |
311 @param type_ type of the calculated metrics |
319 @param type_ type of the calculated metrics |
312 @type str, one of ["raw", "mi", "cc"] |
320 @type str, one of ["raw", "mi", "cc"] |
313 """ |
321 """ |
314 if type_ == "raw": |
322 if type_ == "raw": |
315 self.checkProgress.setMaximum(1) |
323 self.checkProgress.setMaximum(1) |
316 self.checkProgress.setValue(1) |
324 self.checkProgress.setValue(1) |
317 self.__finish() |
325 self.__finish() |
318 |
326 |
319 def __processError(self, type_, fn, msg): |
327 def __processError(self, type_, fn, msg): |
320 """ |
328 """ |
321 Private slot to process an error indication from the service. |
329 Private slot to process an error indication from the service. |
322 |
330 |
323 @param type_ type of the calculated metrics |
331 @param type_ type of the calculated metrics |
324 @type str, one of ["raw", "mi", "cc"] |
332 @type str, one of ["raw", "mi", "cc"] |
325 @param fn filename of the file |
333 @param fn filename of the file |
326 @type str |
334 @type str |
327 @param msg error message |
335 @param msg error message |
328 @type str |
336 @type str |
329 """ |
337 """ |
330 if type_ == "raw": |
338 if type_ == "raw": |
331 self.__createErrorItem(fn, msg) |
339 self.__createErrorItem(fn, msg) |
332 |
340 |
333 def __processResult(self, fn, result): |
341 def __processResult(self, fn, result): |
334 """ |
342 """ |
335 Private slot called after perfoming a code metrics calculation on one |
343 Private slot called after perfoming a code metrics calculation on one |
336 file. |
344 file. |
337 |
345 |
338 @param fn filename of the file |
346 @param fn filename of the file |
339 @type str |
347 @type str |
340 @param result result dict |
348 @param result result dict |
341 @type dict |
349 @type dict |
342 """ |
350 """ |
343 if self.__finished: |
351 if self.__finished: |
344 return |
352 return |
345 |
353 |
346 # Check if it's the requested file, otherwise ignore signal if not |
354 # Check if it's the requested file, otherwise ignore signal if not |
347 # in batch mode |
355 # in batch mode |
348 if not self.__batch and fn != self.filename: |
356 if not self.__batch and fn != self.filename: |
349 return |
357 return |
350 |
358 |
351 QApplication.processEvents() |
359 QApplication.processEvents() |
352 |
360 |
353 if "error" in result: |
361 if "error" in result: |
354 self.__createErrorItem(fn, result["error"]) |
362 self.__createErrorItem(fn, result["error"]) |
355 else: |
363 else: |
356 self.__createResultItem(fn, result) |
364 self.__createResultItem(fn, result) |
357 |
365 |
358 self.progress += 1 |
366 self.progress += 1 |
359 |
367 |
360 self.checkProgress.setValue(self.progress) |
368 self.checkProgress.setValue(self.progress) |
361 QApplication.processEvents() |
369 QApplication.processEvents() |
362 |
370 |
363 if not self.__batch: |
371 if not self.__batch: |
364 self.rawMetrics() |
372 self.rawMetrics() |
365 |
373 |
366 def __getValues(self, result): |
374 def __getValues(self, result): |
367 """ |
375 """ |
368 Private method to extract the code metric values. |
376 Private method to extract the code metric values. |
369 |
377 |
370 @param result result dict |
378 @param result result dict |
371 @type dict |
379 @type dict |
372 @return list of values suitable for display |
380 @return list of values suitable for display |
373 @rtype list of str |
381 @rtype list of str |
374 """ |
382 """ |
375 v = [] |
383 v = [] |
376 for key in ['loc', 'sloc', 'lloc', 'comments', 'multi', |
384 for key in [ |
377 'single_comments', 'blank']: |
385 "loc", |
|
386 "sloc", |
|
387 "lloc", |
|
388 "comments", |
|
389 "multi", |
|
390 "single_comments", |
|
391 "blank", |
|
392 ]: |
378 val = result.get(key, -1) |
393 val = result.get(key, -1) |
379 if val >= 0: |
394 if val >= 0: |
380 v.append(self.__locale.toString(val)) |
395 v.append(self.__locale.toString(val)) |
381 else: |
396 else: |
382 v.append('') |
397 v.append("") |
383 self.__summary[key] += int(val) |
398 self.__summary[key] += int(val) |
384 self.__summary["files"] += 1 |
399 self.__summary["files"] += 1 |
385 return v |
400 return v |
386 |
401 |
387 def __finish(self): |
402 def __finish(self): |
388 """ |
403 """ |
389 Private slot called when the action or the user pressed the button. |
404 Private slot called when the action or the user pressed the button. |
390 """ |
405 """ |
391 if not self.__finished: |
406 if not self.__finished: |
392 self.__finished = True |
407 self.__finished = True |
393 |
408 |
394 # reenable updates of the list |
409 # reenable updates of the list |
395 self.resultList.setSortingEnabled(True) |
410 self.resultList.setSortingEnabled(True) |
396 self.resultList.sortItems(0, Qt.SortOrder.AscendingOrder) |
411 self.resultList.sortItems(0, Qt.SortOrder.AscendingOrder) |
397 self.resultList.setUpdatesEnabled(True) |
412 self.resultList.setUpdatesEnabled(True) |
398 |
413 |
399 self.__createSummary() |
414 self.__createSummary() |
400 |
415 |
401 self.cancelled = True |
416 self.cancelled = True |
402 self.buttonBox.button( |
417 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled( |
403 QDialogButtonBox.StandardButton.Close).setEnabled(True) |
418 True |
404 self.buttonBox.button( |
419 ) |
405 QDialogButtonBox.StandardButton.Cancel).setEnabled(False) |
420 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled( |
406 self.buttonBox.button( |
421 False |
407 QDialogButtonBox.StandardButton.Close).setDefault(True) |
422 ) |
408 |
423 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setDefault( |
|
424 True |
|
425 ) |
|
426 |
409 self.resultList.header().resizeSections( |
427 self.resultList.header().resizeSections( |
410 QHeaderView.ResizeMode.ResizeToContents) |
428 QHeaderView.ResizeMode.ResizeToContents |
|
429 ) |
411 self.resultList.header().setStretchLastSection(True) |
430 self.resultList.header().setStretchLastSection(True) |
412 self.resultList.header().setSectionResizeMode( |
431 self.resultList.header().setSectionResizeMode( |
413 QHeaderView.ResizeMode.Interactive) |
432 QHeaderView.ResizeMode.Interactive |
414 |
433 ) |
|
434 |
415 self.checkProgress.setVisible(False) |
435 self.checkProgress.setVisible(False) |
416 |
436 |
417 def __createSummary(self): |
437 def __createSummary(self): |
418 """ |
438 """ |
419 Private method to create the code metrics summary. |
439 Private method to create the code metrics summary. |
420 """ |
440 """ |
421 self.__createSummaryItem( |
441 self.__createSummaryItem( |
422 self.tr("Files"), self.__locale.toString(self.__summary["files"])) |
442 self.tr("Files"), self.__locale.toString(self.__summary["files"]) |
423 self.__createSummaryItem( |
443 ) |
424 self.tr("LOC"), self.__locale.toString(self.__summary["loc"])) |
444 self.__createSummaryItem( |
425 self.__createSummaryItem( |
445 self.tr("LOC"), self.__locale.toString(self.__summary["loc"]) |
426 self.tr("SLOC"), self.__locale.toString(self.__summary["sloc"])) |
446 ) |
427 self.__createSummaryItem( |
447 self.__createSummaryItem( |
428 self.tr("LLOC"), self.__locale.toString(self.__summary["lloc"])) |
448 self.tr("SLOC"), self.__locale.toString(self.__summary["sloc"]) |
429 self.__createSummaryItem( |
449 ) |
430 self.tr("Comment Lines"), |
450 self.__createSummaryItem( |
431 self.__locale.toString(self.__summary["comments"])) |
451 self.tr("LLOC"), self.__locale.toString(self.__summary["lloc"]) |
|
452 ) |
|
453 self.__createSummaryItem( |
|
454 self.tr("Comment Lines"), self.__locale.toString(self.__summary["comments"]) |
|
455 ) |
432 self.__createSummaryItem( |
456 self.__createSummaryItem( |
433 self.tr("Empty Comments"), |
457 self.tr("Empty Comments"), |
434 self.__locale.toString(self.__summary["single_comments"])) |
458 self.__locale.toString(self.__summary["single_comments"]), |
|
459 ) |
435 self.__createSummaryItem( |
460 self.__createSummaryItem( |
436 self.tr("Multiline Strings"), |
461 self.tr("Multiline Strings"), |
437 self.__locale.toString(self.__summary["multi"])) |
462 self.__locale.toString(self.__summary["multi"]), |
438 self.__createSummaryItem( |
463 ) |
439 self.tr("Empty Lines"), |
464 self.__createSummaryItem( |
440 self.__locale.toString(self.__summary["blank"])) |
465 self.tr("Empty Lines"), self.__locale.toString(self.__summary["blank"]) |
|
466 ) |
441 self.__createSummaryItem( |
467 self.__createSummaryItem( |
442 self.tr("C % L"), |
468 self.tr("C % L"), |
443 "{0:3.0%}".format(min( |
469 "{0:3.0%}".format( |
444 self.__summary["comments"] / ( |
470 min( |
445 float(self.__summary["loc"]) or 1), |
471 self.__summary["comments"] / (float(self.__summary["loc"]) or 1), |
446 1.0)) |
472 1.0, |
|
473 ) |
|
474 ), |
447 ) |
475 ) |
448 self.__createSummaryItem( |
476 self.__createSummaryItem( |
449 self.tr("C % S"), |
477 self.tr("C % S"), |
450 "{0:3.0%}".format(min( |
478 "{0:3.0%}".format( |
451 self.__summary["comments"] / ( |
479 min( |
452 float(self.__summary["sloc"]) or 1), |
480 self.__summary["comments"] / (float(self.__summary["sloc"]) or 1), |
453 1.0)) |
481 1.0, |
|
482 ) |
|
483 ), |
454 ) |
484 ) |
455 self.__createSummaryItem( |
485 self.__createSummaryItem( |
456 self.tr("C + M % L"), |
486 self.tr("C + M % L"), |
457 "{0:3.0%}".format(min( |
487 "{0:3.0%}".format( |
458 (self.__summary["comments"] + self.__summary["multi"]) / ( |
488 min( |
459 float(self.__summary["loc"]) or 1), |
489 (self.__summary["comments"] + self.__summary["multi"]) |
460 1.0)) |
490 / (float(self.__summary["loc"]) or 1), |
461 ) |
491 1.0, |
462 |
492 ) |
|
493 ), |
|
494 ) |
|
495 |
463 self.summaryList.header().resizeSections( |
496 self.summaryList.header().resizeSections( |
464 QHeaderView.ResizeMode.ResizeToContents) |
497 QHeaderView.ResizeMode.ResizeToContents |
|
498 ) |
465 self.summaryList.header().setStretchLastSection(True) |
499 self.summaryList.header().setStretchLastSection(True) |
466 |
500 |
467 def __createSummaryItem(self, col0, col1): |
501 def __createSummaryItem(self, col0, col1): |
468 """ |
502 """ |
469 Private slot to create a new item in the summary list. |
503 Private slot to create a new item in the summary list. |
470 |
504 |
471 @param col0 string for column 0 (string) |
505 @param col0 string for column 0 (string) |
472 @param col1 string for column 1 (string) |
506 @param col1 string for column 1 (string) |
473 """ |
507 """ |
474 itm = QTreeWidgetItem(self.summaryList, [col0, col1]) |
508 itm = QTreeWidgetItem(self.summaryList, [col0, col1]) |
475 itm.setTextAlignment(1, Qt.AlignmentFlag.AlignRight) |
509 itm.setTextAlignment(1, Qt.AlignmentFlag.AlignRight) |
476 |
510 |
477 @pyqtSlot(QAbstractButton) |
511 @pyqtSlot(QAbstractButton) |
478 def on_buttonBox_clicked(self, button): |
512 def on_buttonBox_clicked(self, button): |
479 """ |
513 """ |
480 Private slot called by a button of the button box clicked. |
514 Private slot called by a button of the button box clicked. |
481 |
515 |
482 @param button button that was clicked |
516 @param button button that was clicked |
483 @type QAbstractButton |
517 @type QAbstractButton |
484 """ |
518 """ |
485 if button == self.buttonBox.button( |
519 if button == self.buttonBox.button(QDialogButtonBox.StandardButton.Close): |
486 QDialogButtonBox.StandardButton.Close |
|
487 ): |
|
488 self.close() |
520 self.close() |
489 elif button == self.buttonBox.button( |
521 elif button == self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel): |
490 QDialogButtonBox.StandardButton.Cancel |
|
491 ): |
|
492 if self.__batch: |
522 if self.__batch: |
493 self.radonService.cancelRawMetricsBatch() |
523 self.radonService.cancelRawMetricsBatch() |
494 QTimer.singleShot(1000, self.__finish) |
524 QTimer.singleShot(1000, self.__finish) |
495 else: |
525 else: |
496 self.__finish() |
526 self.__finish() |
497 |
527 |
498 @pyqtSlot() |
528 @pyqtSlot() |
499 def on_startButton_clicked(self): |
529 def on_startButton_clicked(self): |
500 """ |
530 """ |
501 Private slot to start a code metrics run. |
531 Private slot to start a code metrics run. |
502 """ |
532 """ |
503 fileList = self.__fileList[:] |
533 fileList = self.__fileList[:] |
504 |
534 |
505 filterString = self.excludeFilesEdit.text() |
535 filterString = self.excludeFilesEdit.text() |
506 if ( |
536 if ( |
507 "ExcludeFiles" not in self.__data or |
537 "ExcludeFiles" not in self.__data |
508 filterString != self.__data["ExcludeFiles"] |
538 or filterString != self.__data["ExcludeFiles"] |
509 ): |
539 ): |
510 self.__data["ExcludeFiles"] = filterString |
540 self.__data["ExcludeFiles"] = filterString |
511 self.__project.setData( |
541 self.__project.setData("OTHERTOOLSPARMS", "RadonCodeMetrics", self.__data) |
512 "OTHERTOOLSPARMS", "RadonCodeMetrics", self.__data) |
542 filterList = [f.strip() for f in filterString.split(",") if f.strip()] |
513 filterList = [f.strip() for f in filterString.split(",") |
|
514 if f.strip()] |
|
515 if filterList: |
543 if filterList: |
516 for fileFilter in filterList: |
544 for fileFilter in filterList: |
517 fileList = [f for f in fileList |
545 fileList = [f for f in fileList if not fnmatch.fnmatch(f, fileFilter)] |
518 if not fnmatch.fnmatch(f, fileFilter)] |
546 |
519 |
|
520 self.start(fileList) |
547 self.start(fileList) |
521 |
548 |
522 def clear(self): |
549 def clear(self): |
523 """ |
550 """ |
524 Public method to clear all results. |
551 Public method to clear all results. |
525 """ |
552 """ |
526 self.resultList.clear() |
553 self.resultList.clear() |
527 self.summaryList.clear() |
554 self.summaryList.clear() |
528 |
555 |
529 @pyqtSlot(QTreeWidgetItem, int) |
556 @pyqtSlot(QTreeWidgetItem, int) |
530 def on_resultList_itemActivated(self, item, column): |
557 def on_resultList_itemActivated(self, item, column): |
531 """ |
558 """ |
532 Private slot to handle the activation of a result item. |
559 Private slot to handle the activation of a result item. |
533 |
560 |
534 @param item reference to the activated item |
561 @param item reference to the activated item |
535 @type QTreeWidgetItem |
562 @type QTreeWidgetItem |
536 @param column activated column |
563 @param column activated column |
537 @type int |
564 @type int |
538 """ |
565 """ |