• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nens / ThreeDiToolbox / #2592

24 Sep 2025 08:27AM UTC coverage: 34.856% (-0.3%) from 35.146%
#2592

push

coveralls-python

web-flow
Merge 660edfaba into f6f4be1e7

80 of 381 new or added lines in 42 files covered. (21.0%)

9 existing lines in 6 files now uncovered.

4876 of 13989 relevant lines covered (34.86%)

0.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

70.71
/tool_flow_summary/variable_table.py
1

2
from qgis.PyQt.QtCore import QLocale
1✔
3
from qgis.PyQt.QtCore import Qt
1✔
4
from qgis.PyQt.QtWidgets import QAbstractItemView
1✔
5
from qgis.PyQt.QtWidgets import QApplication
1✔
6
from qgis.PyQt.QtWidgets import QHeaderView
1✔
7
from qgis.PyQt.QtWidgets import QTableWidget
1✔
8
from qgis.PyQt.QtWidgets import QTableWidgetItem
1✔
9
from typing import List
1✔
10
from typing import Tuple
1✔
11

12

13
class VariableTable(QTableWidget):
1✔
14
    def __init__(self, variable_alignment, parent):
1✔
15
        super().__init__(0, 1, parent)
1✔
16
        self.variable_alignment = variable_alignment
1✔
17
        self.setHorizontalHeaderLabels([""])
1✔
18
        self.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeMode.Interactive)
1✔
19

20
        self.verticalHeader().hide()
1✔
21
        self.setSortingEnabled(False)
1✔
22
        self.setSelectionMode(QAbstractItemView.SelectionMode.ContiguousSelection)
1✔
23

24
        # for proper aligning, we always need to reserve space for the scrollbar
25
        self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
1✔
26
        self.horizontalHeader().setStretchLastSection(True)
1✔
27

28
        # The list of parameters shown in the summary, idx corresponding to row idx in the table
29
        self.param_names : List[str] = []
1✔
30

31
    def add_summary_results(self, result_text: str, group_data):
1✔
32
        header_item = QTableWidgetItem(result_text)
1✔
33
        self.insertColumn(self.columnCount())
1✔
34
        self.setHorizontalHeaderItem(self.columnCount()-1, header_item)
1✔
35

36
        for param in group_data:
1✔
37
            param_name, param_value = self._format_variable(param, group_data[param])
1✔
38

39
            # Check if we've added this parameter before, then use that row idx,
40
            # otherwise append to bottom of table
41
            try:
1✔
42
                param_index = self.param_names.index(param_name)
1✔
43
            except ValueError:
1✔
44
                param_index = len(self.param_names)
1✔
45
                self.param_names.append(param_name)
1✔
46
                # Add a new row and set the parameter name
47
                assert param_index == self.rowCount()
1✔
48
                self.insertRow(param_index)
1✔
49
                item = QTableWidgetItem(param_name)
1✔
50
                item.setFlags(item.flags() ^ Qt.ItemFlag.ItemIsEditable)
1✔
51
                item.setTextAlignment(Qt.AlignmentFlag.AlignLeft)
1✔
52
                self.setItem(param_index, 0, item)
1✔
53

54
            item = QTableWidgetItem(param_value)
1✔
55
            item.setTextAlignment(self.variable_alignment)
1✔
56
            item.setFlags(item.flags() ^ Qt.ItemFlag.ItemIsEditable)
1✔
57
            self.setItem(param_index, self.columnCount()-1, item)
1✔
58

59
        for idx in range(0, self.columnCount()):
1✔
60
            self.horizontalHeader().setSectionResizeMode(idx, QHeaderView.ResizeMode.Interactive)
1✔
61

62
    def resizeEvent(self, event):
1✔
63
        self.resizeRowsToContents()
×
64
        super().resizeEvent(event)
×
65

66
    def keyPressEvent(self, event):
1✔
67
        # https://stackoverflow.com/questions/1230222/selected-rows-in-qtableview-copy-to-qclipboard/24133289#24133289
NEW
68
        if event.key() == Qt.Key.Key_C and event.modifiers() & Qt.KeyboardModifier.ControlModifier:
×
69

70
            indexes = self.selectedIndexes()
×
71
            current_text = ""
×
72
            current_row = 0  # To determine when to insert newlines
×
73

74
            indexes = sorted(indexes)  # Necessary, otherwise they are in column order
×
75

76
            for index in indexes:
×
77
                if current_text == "":  # first line
×
78
                    pass
×
79
                elif index.row() != current_row:  # new row
×
80
                    current_text += "\n"
×
81
                else:
82
                    current_text += "\t"
×
83

84
                current_row = index.row()
×
85
                current_item = self.item(index.row(), index.column())
×
86
                if current_item:
×
87
                    current_text += str(self.item(index.row(), index.column()).text())
×
88

89
            QApplication.clipboard().setText(current_text)
×
90
            return
×
91

92
        super().keyPressEvent(event)
×
93

94
    def clean_results(self) -> None:
1✔
95
        self.clearContents()
1✔
96
        self.setColumnCount(1)
1✔
97
        self.setRowCount(0)
1✔
98
        self.setHorizontalHeaderLabels([""])
1✔
99
        self.param_names.clear()
1✔
100

101
    def remove_result(self, idx: int) -> None:
1✔
102
        self.removeColumn(idx)
1✔
103

104
    def get_preferred_variable_column_width(self) -> int:
1✔
105
        # iterate over the texts and determine the max width when resized to contents
106
        self.resizeColumnToContents(0)
×
107
        max_width = 0
×
108
        for r in range(self.rowCount()):
×
109
            width = self.columnWidth(0)
×
110
            if width > max_width:
×
111
                max_width = width
×
112

113
        return max_width
×
114

115
    def change_result(self, idx: int, text: str) -> None:
1✔
116
        self.setHorizontalHeaderItem(idx, QTableWidgetItem(text))
×
117

118
    def _format_variable(self, param_name: str, param_data: dict) -> Tuple[str, str]:
1✔
119

120
        param_name = param_name.replace("_", " ")
1✔
121
        if type(param_data) is dict:
1✔
122
            param_name = f'{param_name} [{param_data["units"]}]'
1✔
123
            param_data = param_data["value"]
1✔
124

125
        locale = QLocale()
1✔
126

127
        # numbers in 4 decimals, or scientific notation when not possible
128
        if isinstance(param_data, float):
1✔
129
            if param_data < 0.0001:
1✔
130
                param_data = locale.toString(param_data, "g", 5)
×
131
            else:
132
                param_data = locale.toString(param_data, "f", 4)
1✔
133
        elif isinstance(param_data, int):
1✔
134
            param_data = locale.toString(param_data)
1✔
135
        else:
136
            param_data = str(param_data)
1✔
137

138
        param_name = param_name[0].capitalize() + param_name[1:]
1✔
139
        return param_name, param_data
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc