Skip to content

sequence_widget

frog.gui.measure_script.sequence_widget ¤

Provides a collection of controls for editing a measure script.

Attributes¤

Classes¤

AddButtons(sequence) ¤

Bases: QGroupBox

Buttons for adding new instructions.

Create a new AddButtons.

Source code in frog/gui/measure_script/sequence_widget.py
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
def __init__(self, sequence: SequenceWidget) -> None:
    """Create a new AddButtons."""
    super().__init__("Add instruction")
    self.sequence = sequence

    layout = QVBoxLayout()

    # The number of times to repeat this measurement
    self.count = CountWidget("Measurements")
    layout.addWidget(self.count)

    # Add buttons for preset angles (e.g. zenith, nadir, etc.)
    self.group = QButtonGroup()
    self.group.buttonClicked.connect(self._preset_clicked)
    for preset in ANGLE_PRESETS:
        btn = QPushButton(preset.upper())
        self.group.addButton(btn)
        layout.addWidget(btn)

    # Add button and spinbox for going to a specific angle. Put them next to each
    # other on the same row.
    goto_layout = QHBoxLayout()
    self.angle = QSpinBox()
    self.angle.setSuffix("°")
    self.angle.setMinimum(0)
    self.angle.setMaximum(270)
    self.goto = QPushButton("GOTO")
    self.goto.clicked.connect(self._goto_clicked)
    goto_layout.addWidget(self.angle)
    goto_layout.addWidget(self.goto)

    # Add these widgets to the main layout
    goto_widgets = QWidget()
    goto_widgets.setLayout(goto_layout)
    layout.addWidget(goto_widgets)

    self.setLayout(layout)
Functions¤

ChangeButtons(sequence) ¤

Bases: QGroupBox

Buttons for modifying existing measure instructions.

Create a new ChangeButtons.

Source code in frog/gui/measure_script/sequence_widget.py
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
def __init__(self, sequence: SequenceWidget) -> None:
    """Create a new ChangeButtons."""
    super().__init__("Modify instructions")

    self.up = QPushButton("Up")
    self.up.clicked.connect(sequence.move_selected_up)

    self.down = QPushButton("Down")
    self.down.clicked.connect(sequence.move_selected_down)

    self.delete = QPushButton("Delete")
    self.delete.clicked.connect(sequence.delete_selected)

    self.clear = QPushButton("Clear")
    self.clear.clicked.connect(sequence.delete_all)

    layout = QVBoxLayout()
    layout.addWidget(self.up)
    layout.addWidget(self.down)
    layout.addWidget(self.delete)
    layout.addWidget(self.clear)
    self.setLayout(layout)
Functions¤

SequenceButtons(sequence) ¤

Bases: QWidget

Buttons for changing the sequence of instructions.

Create a new SequenceButtons.

Source code in frog/gui/measure_script/sequence_widget.py
188
189
190
191
192
193
194
195
196
197
198
def __init__(self, sequence: SequenceWidget) -> None:
    """Create a new SequenceButtons."""
    super().__init__()

    add_buttons = AddButtons(sequence)
    change_buttons = ChangeButtons(sequence)

    layout = QVBoxLayout()
    layout.addWidget(add_buttons)
    layout.addWidget(change_buttons)
    self.setLayout(layout)
Functions¤

SequenceModel(sequence) ¤

Bases: QAbstractTableModel

Provides a model of the sequence data for the QTableView.

Create a new SequenceModel.

Parameters:

Name Type Description Default
sequence list[Measurement]

A list of Measurements

required
Source code in frog/gui/measure_script/sequence_widget.py
136
137
138
139
140
141
142
143
def __init__(self, sequence: list[Measurement]) -> None:
    """Create a new SequenceModel.

    Args:
        sequence: A list of Measurements
    """
    super().__init__()
    self._sequence = sequence
Functions¤
columnCount(*args, **kwargs) ¤

Get the number of data columns.

Source code in frog/gui/measure_script/sequence_widget.py
180
181
182
def columnCount(self, *args: Any, **kwargs: Any) -> int:
    """Get the number of data columns."""
    return 2
data(index, role=Qt.ItemDataRole.DisplayRole) ¤

Provides the model's data.

Source code in frog/gui/measure_script/sequence_widget.py
145
146
147
148
149
150
151
152
153
154
155
156
157
158
def data(
    self,
    index: QModelIndex | QPersistentModelIndex,
    role: int = Qt.ItemDataRole.DisplayRole,
) -> Any:
    """Provides the model's data."""
    # Column 0 is angle, column 1 is measurements
    if role == Qt.ItemDataRole.DisplayRole:
        value = getattr(
            self._sequence[index.row()], SequenceModel._COLUMNS[index.column()]
        )
        if isinstance(value, float):
            return f"{value:.0f}°"
        return value
headerData(section, orientation, role=Qt.ItemDataRole.DisplayRole) ¤

Provides header names for the model's data.

Source code in frog/gui/measure_script/sequence_widget.py
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
def headerData(
    self,
    section: int,
    orientation: Qt.Orientation,
    role: int = Qt.ItemDataRole.DisplayRole,
) -> Any:
    """Provides header names for the model's data."""
    # For column names we use Angle and Measurements
    if (
        orientation == Qt.Orientation.Horizontal
        and role == Qt.ItemDataRole.DisplayRole
    ):
        return SequenceModel._COLUMNS[section].title()

    return super().headerData(section, orientation, role)
rowCount(*args, **kwargs) ¤

Get the number of data rows.

Source code in frog/gui/measure_script/sequence_widget.py
176
177
178
def rowCount(self, *args: Any, **kwargs: Any) -> int:
    """Get the number of data rows."""
    return len(self._sequence)

SequenceWidget(sequence=None) ¤

Bases: QWidget

A widget with a table of measure instructions and controls to modify them.

Create a new SequenceWidget.

Source code in frog/gui/measure_script/sequence_widget.py
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
def __init__(self, sequence: list[Measurement] | None = None) -> None:
    """Create a new SequenceWidget."""
    super().__init__()

    self.table = QTableView()

    self.sequence = sequence if sequence else []
    """The sequence of measure instructions as a list of angles and counts."""

    self.model = SequenceModel(self.sequence)
    self.table.setModel(self.model)
    self.table.horizontalHeader().setStretchLastSection(True)
    self.table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)

    self.buttons = SequenceButtons(self)

    # Put the table on the left and the buttons on the right
    layout = QHBoxLayout()
    layout.addWidget(self.table)
    layout.addWidget(self.buttons)
    self.setLayout(layout)
Attributes¤
sequence = sequence if sequence else [] instance-attribute ¤

The sequence of measure instructions as a list of angles and counts.

Functions¤
add_instruction(angle, measurements) ¤

Add a new measure instruction to the sequence.

Parameters:

Name Type Description Default
angle str | float

Target angle as a float or a string corresponding to a preset

required
measurements int

Number of times to take a measurement at this angle

required
Source code in frog/gui/measure_script/sequence_widget.py
49
50
51
52
53
54
55
56
57
58
def add_instruction(self, angle: str | float, measurements: int) -> None:
    """Add a new measure instruction to the sequence.

    Args:
        angle: Target angle as a float or a string corresponding to a preset
        measurements: Number of times to take a measurement at this angle
    """
    self.sequence.append(Measurement(angle, measurements))
    self.model.layoutChanged.emit()
    self.table.scrollToBottom()
delete_all() ¤

Delete all instructions from the table.

Source code in frog/gui/measure_script/sequence_widget.py
122
123
124
125
126
127
def delete_all(self) -> None:
    """Delete all instructions from the table."""
    if self.sequence and self._confirm_delete_all():
        self.model.beginRemoveRows(QModelIndex(), 0, len(self.sequence) - 1)
        self.sequence.clear()
        self.model.endRemoveRows()
delete_selected() ¤

Remove the currently selected instructions from the table.

Source code in frog/gui/measure_script/sequence_widget.py
104
105
106
107
108
109
def delete_selected(self) -> None:
    """Remove the currently selected instructions from the table."""
    for row in self._get_selected_rows(reverse=True):
        self.model.beginRemoveRows(QModelIndex(), row, row)
        self.sequence.pop(row)
        self.model.endRemoveRows()
move_selected_down() ¤

Move the currently selected instructions down one row.

Source code in frog/gui/measure_script/sequence_widget.py
 93
 94
 95
 96
 97
 98
 99
100
101
102
def move_selected_down(self) -> None:
    """Move the currently selected instructions down one row."""
    selected = self._get_selected_rows(reverse=True)
    if not selected or selected[0] == len(self.sequence) - 1:
        # We can't move down if the bottom item is selected
        return

    # Swap each element with the one below it
    for row in selected:
        self._swap_rows(row, row + 1)
move_selected_up() ¤

Move the currently selected instructions up one row.

Source code in frog/gui/measure_script/sequence_widget.py
82
83
84
85
86
87
88
89
90
91
def move_selected_up(self) -> None:
    """Move the currently selected instructions up one row."""
    selected = self._get_selected_rows()
    if not selected or selected[0] == 0:
        # We can't move up if the topmost item is selected
        return

    # Swap each element with the one above it
    for row in selected:
        self._swap_rows(row - 1, row)