51 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) |
51 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) |
52 |
52 |
53 self.resultList.headerItem().setText(self.resultList.columnCount(), "") |
53 self.resultList.headerItem().setText(self.resultList.columnCount(), "") |
54 |
54 |
55 self.radonService = radonService |
55 self.radonService = radonService |
56 self.radonService.metricsDone.connect(self.__processResult) |
56 self.radonService.maintainabilityIndexDone.connect( |
57 self.radonService.metricsError.connect(self.__processError) |
57 self.__processResult) |
|
58 self.radonService.error.connect(self.__processError) |
58 self.radonService.batchFinished.connect(self.__batchFinished) |
59 self.radonService.batchFinished.connect(self.__batchFinished) |
59 |
60 |
60 self.cancelled = False |
61 self.cancelled = False |
61 |
62 |
62 self.__project = e5App().getObject("Project") |
63 self.__project = e5App().getObject("Project") |
63 self.__locale = QLocale() |
64 self.__locale = QLocale() |
|
65 self.__finished = True |
64 |
66 |
65 self.__fileList = [] |
67 self.__fileList = [] |
66 self.filterFrame.setVisible(False) |
68 self.filterFrame.setVisible(False) |
67 |
69 |
68 self.explanationLabel.setText(self.tr( |
70 self.explanationLabel.setText(self.tr( |
88 @param filename name of the file |
90 @param filename name of the file |
89 @type str |
91 @type str |
90 @param values values to be displayed |
92 @param values values to be displayed |
91 @type dict |
93 @type dict |
92 """ |
94 """ |
|
95 # TODO: colorize the rank column according to rank (green, orange, red) |
93 data = [self.__project.getRelativePath(filename)] |
96 data = [self.__project.getRelativePath(filename)] |
94 try: |
97 try: |
95 data.append(self.__locale.toString(float(values["mi"]), "f", 2)) |
98 data.append(self.__locale.toString(float(values["mi"]), "f", 2)) |
96 except ValueError: |
99 except ValueError: |
97 data.append(values["mi"]) |
100 data.append(values["mi"]) |
98 data.append(values["rank"]) |
101 data.append(values["rank"]) |
99 itm = QTreeWidgetItem(self.resultList, data) |
102 itm = QTreeWidgetItem(self.resultList, data) |
100 itm.setTextAlignment(1, Qt.Alignment(Qt.AlignRight)) |
103 itm.setTextAlignment(1, Qt.Alignment(Qt.AlignRight)) |
101 itm.setTextAlignment(2, Qt.Alignment(Qt.AlignHCenter)) |
104 itm.setTextAlignment(2, Qt.Alignment(Qt.AlignHCenter)) |
|
105 |
|
106 if values["rank"] in ["A", "B", "C"]: |
|
107 self.__summary[values["rank"]] += 1 |
102 |
108 |
103 def __createErrorItem(self, filename, message): |
109 def __createErrorItem(self, filename, message): |
104 """ |
110 """ |
105 Private slot to create a new error item in the result list. |
111 Private slot to create a new error item in the result list. |
106 |
112 |
192 self.__batch = False |
200 self.__batch = False |
193 self.maintainabilityIndex() |
201 self.maintainabilityIndex() |
194 else: |
202 else: |
195 self.__batch = True |
203 self.__batch = True |
196 self.maintainabilityIndexBatch() |
204 self.maintainabilityIndexBatch() |
|
205 |
|
206 def maintainabilityIndex(self, codestring=''): |
|
207 """ |
|
208 Public method to start a maintainability index calculation for one |
|
209 Python file. |
|
210 |
|
211 The results are reported to the __processResult slot. |
|
212 |
|
213 @keyparam codestring optional sourcestring |
|
214 @type str |
|
215 """ |
|
216 if not self.files: |
|
217 self.checkProgressLabel.setPath("") |
|
218 self.checkProgress.setMaximum(1) |
|
219 self.checkProgress.setValue(1) |
|
220 self.__finish() |
|
221 return |
|
222 |
|
223 self.filename = self.files.pop(0) |
|
224 self.checkProgress.setValue(self.progress) |
|
225 self.checkProgressLabel.setPath(self.filename) |
|
226 QApplication.processEvents() |
|
227 |
|
228 if self.cancelled: |
|
229 return |
|
230 |
|
231 try: |
|
232 self.source = Utilities.readEncodedFile(self.filename)[0] |
|
233 self.source = Utilities.normalizeCode(self.source) |
|
234 except (UnicodeError, IOError) as msg: |
|
235 self.__createErrorItem(self.filename, str(msg).rstrip()) |
|
236 self.progress += 1 |
|
237 # Continue with next file |
|
238 self.rawMetrics() |
|
239 return |
|
240 |
|
241 self.__finished = False |
|
242 self.radonService.maintainabilityIndex( |
|
243 None, self.filename, self.source) |
|
244 |
|
245 def maintainabilityIndexBatch(self): |
|
246 """ |
|
247 Public method to start a maintainability index calculation batch job. |
|
248 |
|
249 The results are reported to the __processResult slot. |
|
250 """ |
|
251 self.__lastFileItem = None |
|
252 |
|
253 self.checkProgressLabel.setPath(self.tr("Preparing files...")) |
|
254 progress = 0 |
|
255 |
|
256 argumentsList = [] |
|
257 for filename in self.files: |
|
258 progress += 1 |
|
259 self.checkProgress.setValue(progress) |
|
260 QApplication.processEvents() |
|
261 |
|
262 try: |
|
263 source = Utilities.readEncodedFile(filename)[0] |
|
264 source = Utilities.normalizeCode(source) |
|
265 except (UnicodeError, IOError) as msg: |
|
266 self.__createErrorItem(filename, str(msg).rstrip()) |
|
267 continue |
|
268 |
|
269 argumentsList.append((filename, source)) |
|
270 |
|
271 # reset the progress bar to the checked files |
|
272 self.checkProgress.setValue(self.progress) |
|
273 QApplication.processEvents() |
|
274 |
|
275 self.__finished = False |
|
276 self.radonService.maintainabilityIndexBatch(argumentsList) |
|
277 |
|
278 def __batchFinished(self): |
|
279 """ |
|
280 Private slot handling the completion of a batch job. |
|
281 """ |
|
282 self.checkProgressLabel.setPath("") |
|
283 self.checkProgress.setMaximum(1) |
|
284 self.checkProgress.setValue(1) |
|
285 self.__finish() |
|
286 |
|
287 def __processError(self, fn, msg): |
|
288 """ |
|
289 Private slot to process an error indication from the service. |
|
290 |
|
291 @param fn filename of the file |
|
292 @type str |
|
293 @param msg error message |
|
294 @type str |
|
295 """ |
|
296 self.__createErrorItem(fn, msg) |
|
297 |
|
298 def __processResult(self, fn, result): |
|
299 """ |
|
300 Private slot called after perfoming a maintainability index calculation |
|
301 on one file. |
|
302 |
|
303 @param fn filename of the file |
|
304 @type str |
|
305 @param result result dict |
|
306 @type dict |
|
307 """ |
|
308 if self.__finished: |
|
309 return |
|
310 |
|
311 # Check if it's the requested file, otherwise ignore signal if not |
|
312 # in batch mode |
|
313 if not self.__batch and fn != self.filename: |
|
314 return |
|
315 |
|
316 if "error" in result: |
|
317 self.__createErrorItem(fn, result["error"]) |
|
318 else: |
|
319 self.__createResultItem(fn, result) |
|
320 |
|
321 self.progress += 1 |
|
322 |
|
323 self.checkProgress.setValue(self.progress) |
|
324 self.checkProgressLabel.setPath(fn) |
|
325 QApplication.processEvents() |
|
326 |
|
327 if not self.__batch: |
|
328 self.maintainabilityIndex() |
|
329 |
|
330 def __finish(self): |
|
331 """ |
|
332 Private slot called when the action or the user pressed the button. |
|
333 """ |
|
334 if not self.__finished: |
|
335 self.__finished = True |
|
336 |
|
337 # reenable updates of the list |
|
338 self.resultList.setSortingEnabled(True) |
|
339 self.resultList.setUpdatesEnabled(True) |
|
340 |
|
341 self.cancelled = True |
|
342 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) |
|
343 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) |
|
344 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) |
|
345 |
|
346 self.resultList.header().resizeSections( |
|
347 QHeaderView.ResizeToContents) |
|
348 self.resultList.header().setStretchLastSection(True) |
|
349 if qVersion() >= "5.0.0": |
|
350 self.resultList.header().setSectionResizeMode( |
|
351 QHeaderView.Interactive) |
|
352 else: |
|
353 self.resultList.header().setResizeMode(QHeaderView.Interactive) |
|
354 |
|
355 self.summaryLabel.setText(self.tr( |
|
356 "<table>" |
|
357 "<tr><td colspan=2><b>Summary:</b></td></tr>" |
|
358 "<tr><td><b>A</b></td><td>{0} files</td></tr>" |
|
359 "<tr><td><b>B</b></td><td>{1} files</td></tr>" |
|
360 "<tr><td><b>C</b></td><td>{2} files</td></tr>" |
|
361 "</table>" |
|
362 ).format(self.__summary["A"], |
|
363 self.__summary["B"], |
|
364 self.__summary["C"]) |
|
365 ) |
|
366 |
|
367 self.checkProgress.setVisible(False) |
|
368 self.checkProgressLabel.setVisible(False) |
|
369 |
|
370 @pyqtSlot(QAbstractButton) |
|
371 def on_buttonBox_clicked(self, button): |
|
372 """ |
|
373 Private slot called by a button of the button box clicked. |
|
374 |
|
375 @param button button that was clicked |
|
376 @type QAbstractButton |
|
377 """ |
|
378 if button == self.buttonBox.button(QDialogButtonBox.Close): |
|
379 self.close() |
|
380 elif button == self.buttonBox.button(QDialogButtonBox.Cancel): |
|
381 if self.__batch: |
|
382 self.radonService.cancelMaintainabilityIndexBatch() |
|
383 QTimer.singleShot(1000, self.__finish) |
|
384 else: |
|
385 self.__finish() |
|
386 |
|
387 @pyqtSlot() |
|
388 def on_startButton_clicked(self): |
|
389 """ |
|
390 Private slot to start a maintainability index run. |
|
391 """ |
|
392 fileList = self.__fileList[:] |
|
393 |
|
394 filterString = self.excludeFilesEdit.text() |
|
395 if "ExcludeFiles" not in self.__data or \ |
|
396 filterString != self.__data["ExcludeFiles"]: |
|
397 self.__data["ExcludeFiles"] = filterString |
|
398 self.__project.setData( |
|
399 "OTHERTOOLSPARMS", "RadonCodeMetrics", self.__data) |
|
400 filterList = [f.strip() for f in filterString.split(",") |
|
401 if f.strip()] |
|
402 if filterList: |
|
403 for filter in filterList: |
|
404 fileList = \ |
|
405 [f for f in fileList if not fnmatch.fnmatch(f, filter)] |
|
406 |
|
407 self.resultList.clear() |
|
408 self.cancelled = False |
|
409 self.start(fileList) |