28 |
32 |
29 |
33 |
30 class PyCoverageDialog(QDialog, Ui_PyCoverageDialog): |
34 class PyCoverageDialog(QDialog, Ui_PyCoverageDialog): |
31 """ |
35 """ |
32 Class implementing a dialog to display the collected code coverage data. |
36 Class implementing a dialog to display the collected code coverage data. |
33 |
37 |
34 @signal openFile(str) emitted to open the given file in an editor |
38 @signal openFile(str) emitted to open the given file in an editor |
35 """ |
39 """ |
|
40 |
36 openFile = pyqtSignal(str) |
41 openFile = pyqtSignal(str) |
37 |
42 |
38 def __init__(self, parent=None): |
43 def __init__(self, parent=None): |
39 """ |
44 """ |
40 Constructor |
45 Constructor |
41 |
46 |
42 @param parent parent widget |
47 @param parent parent widget |
43 @type QWidget |
48 @type QWidget |
44 """ |
49 """ |
45 super().__init__(parent) |
50 super().__init__(parent) |
46 self.setupUi(self) |
51 self.setupUi(self) |
47 self.setWindowFlags(Qt.WindowType.Window) |
52 self.setWindowFlags(Qt.WindowType.Window) |
48 |
53 |
49 self.buttonBox.button( |
54 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False) |
50 QDialogButtonBox.StandardButton.Close).setEnabled(False) |
55 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True) |
51 self.buttonBox.button( |
56 |
52 QDialogButtonBox.StandardButton.Cancel).setDefault(True) |
57 self.summaryList.headerItem().setText(self.summaryList.columnCount(), "") |
53 |
|
54 self.summaryList.headerItem().setText( |
|
55 self.summaryList.columnCount(), "") |
|
56 self.resultList.headerItem().setText(self.resultList.columnCount(), "") |
58 self.resultList.headerItem().setText(self.resultList.columnCount(), "") |
57 |
59 |
58 self.cancelled = False |
60 self.cancelled = False |
59 self.path = '.' |
61 self.path = "." |
60 self.reload = False |
62 self.reload = False |
61 |
63 |
62 self.excludeList = ['# *pragma[: ]*[nN][oO] *[cC][oO][vV][eE][rR]'] |
64 self.excludeList = ["# *pragma[: ]*[nN][oO] *[cC][oO][vV][eE][rR]"] |
63 |
65 |
64 self.__reportsMenu = QMenu(self.tr("Create Report"), self) |
66 self.__reportsMenu = QMenu(self.tr("Create Report"), self) |
65 self.__reportsMenu.addAction(self.tr("HTML Report"), self.__htmlReport) |
67 self.__reportsMenu.addAction(self.tr("HTML Report"), self.__htmlReport) |
66 self.__reportsMenu.addSeparator() |
68 self.__reportsMenu.addSeparator() |
67 self.__reportsMenu.addAction(self.tr("JSON Report"), self.__jsonReport) |
69 self.__reportsMenu.addAction(self.tr("JSON Report"), self.__jsonReport) |
68 self.__reportsMenu.addAction(self.tr("LCOV Report"), self.__lcovReport) |
70 self.__reportsMenu.addAction(self.tr("LCOV Report"), self.__lcovReport) |
69 |
71 |
70 self.__menu = QMenu(self) |
72 self.__menu = QMenu(self) |
71 self.__menu.addSeparator() |
73 self.__menu.addSeparator() |
72 self.openAct = self.__menu.addAction( |
74 self.openAct = self.__menu.addAction(self.tr("Open"), self.__openFile) |
73 self.tr("Open"), self.__openFile) |
|
74 self.__menu.addSeparator() |
75 self.__menu.addSeparator() |
75 self.__menu.addMenu(self.__reportsMenu) |
76 self.__menu.addMenu(self.__reportsMenu) |
76 self.__menu.addSeparator() |
77 self.__menu.addSeparator() |
77 self.__menu.addAction(self.tr('Erase Coverage Info'), self.__erase) |
78 self.__menu.addAction(self.tr("Erase Coverage Info"), self.__erase) |
78 self.resultList.setContextMenuPolicy( |
79 self.resultList.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) |
79 Qt.ContextMenuPolicy.CustomContextMenu) |
80 self.resultList.customContextMenuRequested.connect(self.__showContextMenu) |
80 self.resultList.customContextMenuRequested.connect( |
81 |
81 self.__showContextMenu) |
|
82 |
|
83 def __format_lines(self, lines): |
82 def __format_lines(self, lines): |
84 """ |
83 """ |
85 Private method to format a list of integers into string by coalescing |
84 Private method to format a list of integers into string by coalescing |
86 groups. |
85 groups. |
87 |
86 |
88 @param lines list of integers |
87 @param lines list of integers |
89 @type list of int |
88 @type list of int |
90 @return string representing the list |
89 @return string representing the list |
91 @rtype str |
90 @rtype str |
92 """ |
91 """ |
93 pairs = [] |
92 pairs = [] |
94 lines.sort() |
93 lines.sort() |
95 maxValue = lines[-1] |
94 maxValue = lines[-1] |
96 start = None |
95 start = None |
97 |
96 |
98 i = lines[0] |
97 i = lines[0] |
99 while i <= maxValue: |
98 while i <= maxValue: |
100 try: |
99 try: |
101 if start is None: |
100 if start is None: |
102 start = i |
101 start = i |
146 @param excluded list of excluded lines |
146 @param excluded list of excluded lines |
147 @type str |
147 @type str |
148 @param missing list of lines without coverage |
148 @param missing list of lines without coverage |
149 @type str |
149 @type str |
150 """ |
150 """ |
151 itm = QTreeWidgetItem(self.resultList, [ |
151 itm = QTreeWidgetItem( |
152 file, |
152 self.resultList, |
153 str(statements), |
153 [ |
154 str(executed), |
154 file, |
155 "{0:.0f}%".format(coverage), |
155 str(statements), |
156 excluded, |
156 str(executed), |
157 missing |
157 "{0:.0f}%".format(coverage), |
158 ]) |
158 excluded, |
|
159 missing, |
|
160 ], |
|
161 ) |
159 for col in range(1, 4): |
162 for col in range(1, 4): |
160 itm.setTextAlignment(col, Qt.AlignmentFlag.AlignRight) |
163 itm.setTextAlignment(col, Qt.AlignmentFlag.AlignRight) |
161 if statements != executed: |
164 if statements != executed: |
162 font = itm.font(0) |
165 font = itm.font(0) |
163 font.setBold(True) |
166 font.setBold(True) |
164 for col in range(itm.columnCount()): |
167 for col in range(itm.columnCount()): |
165 itm.setFont(col, font) |
168 itm.setFont(col, font) |
166 |
169 |
167 def start(self, cfn, fn): |
170 def start(self, cfn, fn): |
168 """ |
171 """ |
169 Public slot to start the coverage data evaluation. |
172 Public slot to start the coverage data evaluation. |
170 |
173 |
171 @param cfn basename of the coverage file |
174 @param cfn basename of the coverage file |
172 @type str |
175 @type str |
173 @param fn file or list of files or directory to be checked |
176 @param fn file or list of files or directory to be checked |
174 @type str or list of str |
177 @type str or list of str |
175 """ |
178 """ |
176 # initialize the dialog |
179 # initialize the dialog |
177 self.resultList.clear() |
180 self.resultList.clear() |
178 self.summaryList.clear() |
181 self.summaryList.clear() |
179 self.cancelled = False |
182 self.cancelled = False |
180 self.buttonBox.button( |
183 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False) |
181 QDialogButtonBox.StandardButton.Close).setEnabled(False) |
184 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(True) |
182 self.buttonBox.button( |
185 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True) |
183 QDialogButtonBox.StandardButton.Cancel).setEnabled(True) |
186 |
184 self.buttonBox.button( |
|
185 QDialogButtonBox.StandardButton.Cancel).setDefault(True) |
|
186 |
|
187 self.__cfn = cfn |
187 self.__cfn = cfn |
188 self.__fn = fn |
188 self.__fn = fn |
189 |
189 |
190 self.cfn = ( |
190 self.cfn = ( |
191 cfn |
191 cfn |
192 if cfn.endswith(".coverage") else |
192 if cfn.endswith(".coverage") |
193 "{0}.coverage".format(os.path.splitext(cfn)[0]) |
193 else "{0}.coverage".format(os.path.splitext(cfn)[0]) |
194 ) |
194 ) |
195 |
195 |
196 if isinstance(fn, list): |
196 if isinstance(fn, list): |
197 files = fn |
197 files = fn |
198 self.path = os.path.dirname(cfn) |
198 self.path = os.path.dirname(cfn) |
199 elif os.path.isdir(fn): |
199 elif os.path.isdir(fn): |
200 files = Utilities.direntries(fn, True, '*.py', False) |
200 files = Utilities.direntries(fn, True, "*.py", False) |
201 self.path = fn |
201 self.path = fn |
202 else: |
202 else: |
203 files = [fn] |
203 files = [fn] |
204 self.path = os.path.dirname(cfn) |
204 self.path = os.path.dirname(cfn) |
205 files.sort() |
205 files.sort() |
206 |
206 |
207 cover = Coverage(data_file=self.cfn) |
207 cover = Coverage(data_file=self.cfn) |
208 cover.load() |
208 cover.load() |
209 |
209 |
210 # set the exclude pattern |
210 # set the exclude pattern |
211 self.excludeCombo.clear() |
211 self.excludeCombo.clear() |
212 self.excludeCombo.addItems(self.excludeList) |
212 self.excludeCombo.addItems(self.excludeList) |
213 |
213 |
214 self.checkProgress.setMaximum(len(files)) |
214 self.checkProgress.setMaximum(len(files)) |
215 QApplication.processEvents() |
215 QApplication.processEvents() |
216 |
216 |
217 total_statements = 0 |
217 total_statements = 0 |
218 total_executed = 0 |
218 total_executed = 0 |
219 total_exceptions = 0 |
219 total_exceptions = 0 |
220 |
220 |
221 cover.exclude(self.excludeList[0]) |
221 cover.exclude(self.excludeList[0]) |
222 |
222 |
223 try: |
223 try: |
224 # disable updates of the list for speed |
224 # disable updates of the list for speed |
225 self.resultList.setUpdatesEnabled(False) |
225 self.resultList.setUpdatesEnabled(False) |
226 self.resultList.setSortingEnabled(False) |
226 self.resultList.setSortingEnabled(False) |
227 |
227 |
228 # now go through all the files |
228 # now go through all the files |
229 now = time.monotonic() |
229 now = time.monotonic() |
230 for progress, file in enumerate(files, start=1): |
230 for progress, file in enumerate(files, start=1): |
231 if self.cancelled: |
231 if self.cancelled: |
232 return |
232 return |
233 |
233 |
234 try: |
234 try: |
235 statements, excluded, missing, readable = ( |
235 statements, excluded, missing, readable = cover.analysis2(file)[1:] |
236 cover.analysis2(file)[1:]) |
236 readableEx = excluded and self.__format_lines(excluded) or "" |
237 readableEx = (excluded and self.__format_lines(excluded) or |
|
238 '') |
|
239 n = len(statements) |
237 n = len(statements) |
240 m = n - len(missing) |
238 m = n - len(missing) |
241 pc = 100.0 * m / n if n > 0 else 100.0 |
239 pc = 100.0 * m / n if n > 0 else 100.0 |
242 self.__createResultItem( |
240 self.__createResultItem( |
243 file, str(n), str(m), pc, readableEx, readable) |
241 file, str(n), str(m), pc, readableEx, readable |
244 |
242 ) |
|
243 |
245 total_statements += n |
244 total_statements += n |
246 total_executed += m |
245 total_executed += m |
247 except CoverageException: |
246 except CoverageException: |
248 total_exceptions += 1 |
247 total_exceptions += 1 |
249 |
248 |
250 self.checkProgress.setValue(progress) |
249 self.checkProgress.setValue(progress) |
251 if time.monotonic() - now > 0.01: |
250 if time.monotonic() - now > 0.01: |
252 QApplication.processEvents() |
251 QApplication.processEvents() |
253 now = time.monotonic() |
252 now = time.monotonic() |
254 finally: |
253 finally: |
255 # reenable updates of the list |
254 # reenable updates of the list |
256 self.resultList.setSortingEnabled(True) |
255 self.resultList.setSortingEnabled(True) |
257 self.resultList.setUpdatesEnabled(True) |
256 self.resultList.setUpdatesEnabled(True) |
258 self.checkProgress.reset() |
257 self.checkProgress.reset() |
259 |
258 |
260 # show summary info |
259 # show summary info |
261 if len(files) > 1: |
260 if len(files) > 1: |
262 if total_statements > 0: |
261 if total_statements > 0: |
263 pc = 100.0 * total_executed / total_statements |
262 pc = 100.0 * total_executed / total_statements |
264 else: |
263 else: |
265 pc = 100.0 |
264 pc = 100.0 |
266 itm = QTreeWidgetItem(self.summaryList, [ |
265 itm = QTreeWidgetItem( |
267 str(total_statements), |
266 self.summaryList, |
268 str(total_executed), |
267 [str(total_statements), str(total_executed), "{0:.0f}%".format(pc)], |
269 "{0:.0f}%".format(pc) |
268 ) |
270 ]) |
|
271 for col in range(0, 3): |
269 for col in range(0, 3): |
272 itm.setTextAlignment(col, Qt.AlignmentFlag.AlignRight) |
270 itm.setTextAlignment(col, Qt.AlignmentFlag.AlignRight) |
273 else: |
271 else: |
274 self.summaryGroup.hide() |
272 self.summaryGroup.hide() |
275 |
273 |
276 if total_exceptions: |
274 if total_exceptions: |
277 EricMessageBox.warning( |
275 EricMessageBox.warning( |
278 self, |
276 self, |
279 self.tr("Parse Error"), |
277 self.tr("Parse Error"), |
280 self.tr("""%n file(s) could not be parsed. Coverage""" |
278 self.tr( |
281 """ info for these is not available.""", "", |
279 """%n file(s) could not be parsed. Coverage""" |
282 total_exceptions)) |
280 """ info for these is not available.""", |
283 |
281 "", |
|
282 total_exceptions, |
|
283 ), |
|
284 ) |
|
285 |
284 self.__finish() |
286 self.__finish() |
285 |
287 |
286 def __finish(self): |
288 def __finish(self): |
287 """ |
289 """ |
288 Private slot called when the action finished or the user pressed the |
290 Private slot called when the action finished or the user pressed the |
289 button. |
291 button. |
290 """ |
292 """ |
291 self.cancelled = True |
293 self.cancelled = True |
292 self.buttonBox.button( |
294 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(True) |
293 QDialogButtonBox.StandardButton.Close).setEnabled(True) |
295 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(False) |
294 self.buttonBox.button( |
296 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setDefault(True) |
295 QDialogButtonBox.StandardButton.Cancel).setEnabled(False) |
|
296 self.buttonBox.button( |
|
297 QDialogButtonBox.StandardButton.Close).setDefault(True) |
|
298 QApplication.processEvents() |
297 QApplication.processEvents() |
299 self.resultList.header().resizeSections( |
298 self.resultList.header().resizeSections(QHeaderView.ResizeMode.ResizeToContents) |
300 QHeaderView.ResizeMode.ResizeToContents) |
|
301 self.resultList.header().setStretchLastSection(True) |
299 self.resultList.header().setStretchLastSection(True) |
302 self.summaryList.header().resizeSections( |
300 self.summaryList.header().resizeSections( |
303 QHeaderView.ResizeMode.ResizeToContents) |
301 QHeaderView.ResizeMode.ResizeToContents |
|
302 ) |
304 self.summaryList.header().setStretchLastSection(True) |
303 self.summaryList.header().setStretchLastSection(True) |
305 |
304 |
306 def on_buttonBox_clicked(self, button): |
305 def on_buttonBox_clicked(self, button): |
307 """ |
306 """ |
308 Private slot called by a button of the button box clicked. |
307 Private slot called by a button of the button box clicked. |
309 |
308 |
310 @param button button that was clicked |
309 @param button button that was clicked |
311 @type QAbstractButton |
310 @type QAbstractButton |
312 """ |
311 """ |
313 if button == self.buttonBox.button( |
312 if button == self.buttonBox.button(QDialogButtonBox.StandardButton.Close): |
314 QDialogButtonBox.StandardButton.Close |
|
315 ): |
|
316 self.close() |
313 self.close() |
317 elif button == self.buttonBox.button( |
314 elif button == self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel): |
318 QDialogButtonBox.StandardButton.Cancel |
|
319 ): |
|
320 self.__finish() |
315 self.__finish() |
321 |
316 |
322 def __showContextMenu(self, coord): |
317 def __showContextMenu(self, coord): |
323 """ |
318 """ |
324 Private slot to show the context menu of the listview. |
319 Private slot to show the context menu of the listview. |
325 |
320 |
326 @param coord position of the mouse pointer |
321 @param coord position of the mouse pointer |
327 @type QPoint |
322 @type QPoint |
328 """ |
323 """ |
329 itm = self.resultList.itemAt(coord) |
324 itm = self.resultList.itemAt(coord) |
330 if itm: |
325 if itm: |
331 self.openAct.setEnabled(True) |
326 self.openAct.setEnabled(True) |
332 else: |
327 else: |
333 self.openAct.setEnabled(False) |
328 self.openAct.setEnabled(False) |
334 self.__reportsMenu.setEnabled( |
329 self.__reportsMenu.setEnabled(bool(self.resultList.topLevelItemCount())) |
335 bool(self.resultList.topLevelItemCount())) |
|
336 self.__menu.popup(self.mapToGlobal(coord)) |
330 self.__menu.popup(self.mapToGlobal(coord)) |
337 |
331 |
338 def __openFile(self, itm=None): |
332 def __openFile(self, itm=None): |
339 """ |
333 """ |
340 Private slot to open the selected file. |
334 Private slot to open the selected file. |
341 |
335 |
342 @param itm reference to the item to be opened |
336 @param itm reference to the item to be opened |
343 @type QTreeWidgetItem |
337 @type QTreeWidgetItem |
344 """ |
338 """ |
345 if itm is None: |
339 if itm is None: |
346 itm = self.resultList.currentItem() |
340 itm = self.resultList.currentItem() |
347 fn = itm.text(0) |
341 fn = itm.text(0) |
348 |
342 |
349 try: |
343 try: |
350 vm = ericApp().getObject("ViewManager") |
344 vm = ericApp().getObject("ViewManager") |
351 vm.openSourceFile(fn) |
345 vm.openSourceFile(fn) |
352 editor = vm.getOpenEditor(fn) |
346 editor = vm.getOpenEditor(fn) |
353 editor.codeCoverageShowAnnotations(coverageFile=self.cfn) |
347 editor.codeCoverageShowAnnotations(coverageFile=self.cfn) |
354 except KeyError: |
348 except KeyError: |
355 self.openFile.emit(fn) |
349 self.openFile.emit(fn) |
356 |
350 |
357 def __prepareReportGeneration(self): |
351 def __prepareReportGeneration(self): |
358 """ |
352 """ |
359 Private method to prepare a report generation. |
353 Private method to prepare a report generation. |
360 |
354 |
361 @return tuple containing a reference to the Coverage object and the |
355 @return tuple containing a reference to the Coverage object and the |
362 list of files to report |
356 list of files to report |
363 @rtype tuple of (Coverage, list of str) |
357 @rtype tuple of (Coverage, list of str) |
364 """ |
358 """ |
365 count = self.resultList.topLevelItemCount() |
359 count = self.resultList.topLevelItemCount() |
366 if count == 0: |
360 if count == 0: |
367 return None, [] |
361 return None, [] |
368 |
362 |
369 # get list of all filenames |
363 # get list of all filenames |
370 files = [ |
364 files = [self.resultList.topLevelItem(index).text(0) for index in range(count)] |
371 self.resultList.topLevelItem(index).text(0) |
365 |
372 for index in range(count) |
|
373 ] |
|
374 |
|
375 cover = Coverage(data_file=self.cfn) |
366 cover = Coverage(data_file=self.cfn) |
376 cover.exclude(self.excludeList[0]) |
367 cover.exclude(self.excludeList[0]) |
377 cover.load() |
368 cover.load() |
378 |
369 |
379 return cover, files |
370 return cover, files |
380 |
371 |
381 @pyqtSlot() |
372 @pyqtSlot() |
382 def __htmlReport(self): |
373 def __htmlReport(self): |
383 """ |
374 """ |
384 Private slot to generate a HTML report of the shown data. |
375 Private slot to generate a HTML report of the shown data. |
385 """ |
376 """ |
386 from .PyCoverageHtmlReportDialog import PyCoverageHtmlReportDialog |
377 from .PyCoverageHtmlReportDialog import PyCoverageHtmlReportDialog |
387 |
378 |
388 dlg = PyCoverageHtmlReportDialog(os.path.dirname(self.cfn), self) |
379 dlg = PyCoverageHtmlReportDialog(os.path.dirname(self.cfn), self) |
389 if dlg.exec() == QDialog.DialogCode.Accepted: |
380 if dlg.exec() == QDialog.DialogCode.Accepted: |
390 title, outputDirectory, extraCSS, openReport = dlg.getData() |
381 title, outputDirectory, extraCSS, openReport = dlg.getData() |
391 |
382 |
392 cover, files = self.__prepareReportGeneration() |
383 cover, files = self.__prepareReportGeneration() |
393 cover.html_report(morfs=files, directory=outputDirectory, |
384 cover.html_report( |
394 ignore_errors=True, extra_css=extraCSS, |
385 morfs=files, |
395 title=title) |
386 directory=outputDirectory, |
396 |
387 ignore_errors=True, |
|
388 extra_css=extraCSS, |
|
389 title=title, |
|
390 ) |
|
391 |
397 if openReport: |
392 if openReport: |
398 QDesktopServices.openUrl(QUrl.fromLocalFile(os.path.join( |
393 QDesktopServices.openUrl( |
399 outputDirectory, "index.html"))) |
394 QUrl.fromLocalFile(os.path.join(outputDirectory, "index.html")) |
400 |
395 ) |
|
396 |
401 @pyqtSlot() |
397 @pyqtSlot() |
402 def __jsonReport(self): |
398 def __jsonReport(self): |
403 """ |
399 """ |
404 Private slot to generate a JSON report of the shown data. |
400 Private slot to generate a JSON report of the shown data. |
405 """ |
401 """ |
406 from .PyCoverageJsonReportDialog import PyCoverageJsonReportDialog |
402 from .PyCoverageJsonReportDialog import PyCoverageJsonReportDialog |
407 |
403 |
408 dlg = PyCoverageJsonReportDialog(os.path.dirname(self.cfn), self) |
404 dlg = PyCoverageJsonReportDialog(os.path.dirname(self.cfn), self) |
409 if dlg.exec() == QDialog.DialogCode.Accepted: |
405 if dlg.exec() == QDialog.DialogCode.Accepted: |
410 filename, compact = dlg.getData() |
406 filename, compact = dlg.getData() |
411 cover, files = self.__prepareReportGeneration() |
407 cover, files = self.__prepareReportGeneration() |
412 cover.json_report(morfs=files, outfile=filename, |
408 cover.json_report( |
413 ignore_errors=True, pretty_print=not compact) |
409 morfs=files, |
414 |
410 outfile=filename, |
|
411 ignore_errors=True, |
|
412 pretty_print=not compact, |
|
413 ) |
|
414 |
415 @pyqtSlot() |
415 @pyqtSlot() |
416 def __lcovReport(self): |
416 def __lcovReport(self): |
417 """ |
417 """ |
418 Private slot to generate a LCOV report of the shown data. |
418 Private slot to generate a LCOV report of the shown data. |
419 """ |
419 """ |
420 from EricWidgets import EricPathPickerDialog |
420 from EricWidgets import EricPathPickerDialog |
421 from EricWidgets.EricPathPicker import EricPathPickerModes |
421 from EricWidgets.EricPathPicker import EricPathPickerModes |
422 |
422 |
423 filename, ok = EricPathPickerDialog.getPath( |
423 filename, ok = EricPathPickerDialog.getPath( |
424 self, |
424 self, |
425 self.tr("LCOV Report"), |
425 self.tr("LCOV Report"), |
426 self.tr("Enter the path of the output file:"), |
426 self.tr("Enter the path of the output file:"), |
427 mode=EricPathPickerModes.SAVE_FILE_ENSURE_EXTENSION_MODE, |
427 mode=EricPathPickerModes.SAVE_FILE_ENSURE_EXTENSION_MODE, |
428 path=os.path.join(os.path.dirname(self.cfn), "coverage.lcov"), |
428 path=os.path.join(os.path.dirname(self.cfn), "coverage.lcov"), |
429 defaultDirectory=os.path.dirname(self.cfn), |
429 defaultDirectory=os.path.dirname(self.cfn), |
430 filters=self.tr("LCOV Files (*.lcov);;All Files (*)") |
430 filters=self.tr("LCOV Files (*.lcov);;All Files (*)"), |
431 ) |
431 ) |
432 if ok: |
432 if ok: |
433 cover, files = self.__prepareReportGeneration() |
433 cover, files = self.__prepareReportGeneration() |
434 cover.lcov_report(morfs=files, outfile=filename, |
434 cover.lcov_report(morfs=files, outfile=filename, ignore_errors=True) |
435 ignore_errors=True) |
435 |
436 |
|
437 def __erase(self): |
436 def __erase(self): |
438 """ |
437 """ |
439 Private slot to handle the erase context menu action. |
438 Private slot to handle the erase context menu action. |
440 |
439 |
441 This method erases the collected coverage data that is |
440 This method erases the collected coverage data that is |
442 stored in the .coverage file. |
441 stored in the .coverage file. |
443 """ |
442 """ |
444 cover = Coverage(data_file=self.cfn) |
443 cover = Coverage(data_file=self.cfn) |
445 cover.load() |
444 cover.load() |
446 cover.erase() |
445 cover.erase() |
447 |
446 |
448 self.reloadButton.setEnabled(False) |
447 self.reloadButton.setEnabled(False) |
449 self.resultList.clear() |
448 self.resultList.clear() |
450 self.summaryList.clear() |
449 self.summaryList.clear() |
451 |
450 |
452 @pyqtSlot() |
451 @pyqtSlot() |
453 def on_reloadButton_clicked(self): |
452 def on_reloadButton_clicked(self): |
454 """ |
453 """ |
455 Private slot to reload the coverage info. |
454 Private slot to reload the coverage info. |
456 """ |
455 """ |