RadonMetrics/RawMetricsDialog.py

branch
eric7
changeset 94
725eaca7bc4b
parent 93
1ae73306422a
child 102
f7b964ea22a1
equal deleted inserted replaced
93:1ae73306422a 94:725eaca7bc4b
10 import os 10 import os
11 import fnmatch 11 import fnmatch
12 12
13 from PyQt6.QtCore import pyqtSlot, Qt, QTimer, QLocale 13 from PyQt6.QtCore import pyqtSlot, Qt, QTimer, QLocale
14 from PyQt6.QtWidgets import ( 14 from PyQt6.QtWidgets import (
15 QDialog, QDialogButtonBox, QAbstractButton, QHeaderView, QTreeWidgetItem, 15 QDialog,
16 QApplication 16 QDialogButtonBox,
17 QAbstractButton,
18 QHeaderView,
19 QTreeWidgetItem,
20 QApplication,
17 ) 21 )
18 22
19 from .Ui_RawMetricsDialog import Ui_RawMetricsDialog 23 from .Ui_RawMetricsDialog import Ui_RawMetricsDialog
20 24
21 from EricWidgets.EricApplication import ericApp 25 from EricWidgets.EricApplication import ericApp
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&nbsp;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&nbsp;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 """

eric ide

mercurial