1#  NanoVNASaver
2#
3#  A python program to view and export Touchstone data from a NanoVNA
4#  Copyright (C) 2019, 2020  Rune B. Broberg
5#  Copyright (C) 2020 NanoVNA-Saver Authors
6#
7#  This program is free software: you can redistribute it and/or modify
8#  it under the terms of the GNU General Public License as published by
9#  the Free Software Foundation, either version 3 of the License, or
10#  (at your option) any later version.
11#
12#  This program is distributed in the hope that it will be useful,
13#  but WITHOUT ANY WARRANTY; without even the implied warranty of
14#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15#  GNU General Public License for more details.
16#
17#  You should have received a copy of the GNU General Public License
18#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
19import logging
20from typing import List
21
22from PyQt5 import QtWidgets, QtCore, QtGui
23
24from NanoVNASaver.Windows.Bands import BandsWindow
25from NanoVNASaver.Windows.MarkerSettings import MarkerSettingsWindow
26from NanoVNASaver.Marker import Marker
27logger = logging.getLogger(__name__)
28
29
30class DisplaySettingsWindow(QtWidgets.QWidget):
31    def __init__(self, app: QtWidgets.QWidget):
32        super().__init__()
33
34        self.app = app
35        self.setWindowTitle("Display settings")
36        self.setWindowIcon(self.app.icon)
37
38        self.marker_window = MarkerSettingsWindow(self.app)
39
40        QtWidgets.QShortcut(QtCore.Qt.Key_Escape, self, self.hide)
41
42        layout = QtWidgets.QHBoxLayout()
43        self.setLayout(layout)
44
45        left_layout = QtWidgets.QVBoxLayout()
46        layout.addLayout(left_layout)
47
48        display_options_box = QtWidgets.QGroupBox("Options")
49        display_options_layout = QtWidgets.QFormLayout(display_options_box)
50
51        self.returnloss_group = QtWidgets.QButtonGroup()
52        self.returnloss_is_negative = QtWidgets.QRadioButton("Negative")
53        self.returnloss_is_positive = QtWidgets.QRadioButton("Positive")
54        self.returnloss_group.addButton(self.returnloss_is_positive)
55        self.returnloss_group.addButton(self.returnloss_is_negative)
56
57        display_options_layout.addRow("Return loss is:", self.returnloss_is_negative)
58        display_options_layout.addRow("", self.returnloss_is_positive)
59
60        if self.app.settings.value("ReturnLossPositive", False, bool):
61            self.returnloss_is_positive.setChecked(True)
62        else:
63            self.returnloss_is_negative.setChecked(True)
64
65        self.returnloss_is_positive.toggled.connect(self.changeReturnLoss)
66        self.changeReturnLoss()
67
68        self.show_lines_option = QtWidgets.QCheckBox("Show lines")
69        show_lines_label = QtWidgets.QLabel("Displays a thin line between data points")
70        self.show_lines_option.stateChanged.connect(self.changeShowLines)
71        display_options_layout.addRow(self.show_lines_option, show_lines_label)
72
73        self.dark_mode_option = QtWidgets.QCheckBox("Dark mode")
74        dark_mode_label = QtWidgets.QLabel("Black background with white text")
75        self.dark_mode_option.stateChanged.connect(self.changeDarkMode)
76        display_options_layout.addRow(self.dark_mode_option, dark_mode_label)
77
78        self.btnColorPicker = QtWidgets.QPushButton("█")
79        self.btnColorPicker.setFixedWidth(20)
80        self.sweepColor = self.app.settings.value(
81            "SweepColor", defaultValue=QtGui.QColor(160, 140, 20, 128),
82            type=QtGui.QColor)
83        self.setSweepColor(self.sweepColor)
84        self.btnColorPicker.clicked.connect(lambda: self.setSweepColor(
85            QtWidgets.QColorDialog.getColor(
86                self.sweepColor, options=QtWidgets.QColorDialog.ShowAlphaChannel)))
87
88        display_options_layout.addRow("Sweep color", self.btnColorPicker)
89
90        self.btnSecondaryColorPicker = QtWidgets.QPushButton("█")
91        self.btnSecondaryColorPicker.setFixedWidth(20)
92        self.secondarySweepColor = self.app.settings.value("SecondarySweepColor",
93                                                           defaultValue=QtGui.QColor(
94                                                               20, 160, 140, 128),
95                                                           type=QtGui.QColor)
96        self.setSecondarySweepColor(self.secondarySweepColor)
97        self.btnSecondaryColorPicker.clicked.connect(lambda: self.setSecondarySweepColor(
98            QtWidgets.QColorDialog.getColor(self.secondarySweepColor,
99                                            options=QtWidgets.QColorDialog.ShowAlphaChannel)))
100
101        display_options_layout.addRow("Second sweep color", self.btnSecondaryColorPicker)
102
103        self.btnReferenceColorPicker = QtWidgets.QPushButton("█")
104        self.btnReferenceColorPicker.setFixedWidth(20)
105        self.referenceColor = self.app.settings.value(
106            "ReferenceColor", defaultValue=QtGui.QColor(0, 0, 255, 48),
107            type=QtGui.QColor)
108        self.setReferenceColor(self.referenceColor)
109        self.btnReferenceColorPicker.clicked.connect(lambda: self.setReferenceColor(
110            QtWidgets.QColorDialog.getColor(
111                self.referenceColor, options=QtWidgets.QColorDialog.ShowAlphaChannel)))
112
113        display_options_layout.addRow("Reference color", self.btnReferenceColorPicker)
114
115        self.btnSecondaryReferenceColorPicker = QtWidgets.QPushButton("█")
116        self.btnSecondaryReferenceColorPicker.setFixedWidth(20)
117        self.secondaryReferenceColor = self.app.settings.value(
118            "SecondaryReferenceColor",
119            defaultValue=QtGui.QColor(0, 0, 255, 48),
120            type=QtGui.QColor)
121        self.setSecondaryReferenceColor(self.secondaryReferenceColor)
122        self.btnSecondaryReferenceColorPicker.clicked.connect(
123            lambda: self.setSecondaryReferenceColor(
124                QtWidgets.QColorDialog.getColor(
125                    self.secondaryReferenceColor,
126                    options=QtWidgets.QColorDialog.ShowAlphaChannel)))
127
128        display_options_layout.addRow(
129            "Second reference color",
130            self.btnSecondaryReferenceColorPicker)
131
132        self.pointSizeInput = QtWidgets.QSpinBox()
133        pointsize = self.app.settings.value("PointSize", 2, int)
134        self.pointSizeInput.setValue(pointsize)
135        self.changePointSize(pointsize)
136        self.pointSizeInput.setMinimum(1)
137        self.pointSizeInput.setMaximum(10)
138        self.pointSizeInput.setSuffix(" px")
139        self.pointSizeInput.setAlignment(QtCore.Qt.AlignRight)
140        self.pointSizeInput.valueChanged.connect(self.changePointSize)
141        display_options_layout.addRow("Point size", self.pointSizeInput)
142
143        self.lineThicknessInput = QtWidgets.QSpinBox()
144        linethickness = self.app.settings.value("LineThickness", 1, int)
145        self.lineThicknessInput.setValue(linethickness)
146        self.changeLineThickness(linethickness)
147        self.lineThicknessInput.setMinimum(1)
148        self.lineThicknessInput.setMaximum(10)
149        self.lineThicknessInput.setSuffix(" px")
150        self.lineThicknessInput.setAlignment(QtCore.Qt.AlignRight)
151        self.lineThicknessInput.valueChanged.connect(self.changeLineThickness)
152        display_options_layout.addRow("Line thickness", self.lineThicknessInput)
153
154        self.markerSizeInput = QtWidgets.QSpinBox()
155        markersize = self.app.settings.value("MarkerSize", 6, int)
156        self.markerSizeInput.setValue(markersize)
157        self.changeMarkerSize(markersize)
158        self.markerSizeInput.setMinimum(4)
159        self.markerSizeInput.setMaximum(20)
160        self.markerSizeInput.setSingleStep(2)
161        self.markerSizeInput.setSuffix(" px")
162        self.markerSizeInput.setAlignment(QtCore.Qt.AlignRight)
163        self.markerSizeInput.valueChanged.connect(self.changeMarkerSize)
164        self.markerSizeInput.editingFinished.connect(self.validateMarkerSize)
165        display_options_layout.addRow("Marker size", self.markerSizeInput)
166
167        self.show_marker_number_option = QtWidgets.QCheckBox("Show marker numbers")
168        show_marker_number_label = QtWidgets.QLabel("Displays the marker number next to the marker")
169        self.show_marker_number_option.stateChanged.connect(self.changeShowMarkerNumber)
170        display_options_layout.addRow(self.show_marker_number_option, show_marker_number_label)
171
172        self.filled_marker_option = QtWidgets.QCheckBox("Filled markers")
173        filled_marker_label = QtWidgets.QLabel("Shows the marker as a filled triangle")
174        self.filled_marker_option.stateChanged.connect(self.changeFilledMarkers)
175        display_options_layout.addRow(self.filled_marker_option, filled_marker_label)
176
177        self.marker_tip_group = QtWidgets.QButtonGroup()
178        self.marker_at_center = QtWidgets.QRadioButton("At the center of the marker")
179        self.marker_at_tip = QtWidgets.QRadioButton("At the tip of the marker")
180        self.marker_tip_group.addButton(self.marker_at_center)
181        self.marker_tip_group.addButton(self.marker_at_tip)
182
183        display_options_layout.addRow("Data point is:", self.marker_at_center)
184        display_options_layout.addRow("", self.marker_at_tip)
185
186        if self.app.settings.value("MarkerAtTip", False, bool):
187            self.marker_at_tip.setChecked(True)
188        else:
189            self.marker_at_center.setChecked(True)
190
191        self.marker_at_tip.toggled.connect(self.changeMarkerAtTip)
192        self.changeMarkerAtTip()
193
194        color_options_box = QtWidgets.QGroupBox("Chart colors")
195        color_options_layout = QtWidgets.QFormLayout(color_options_box)
196
197        self.use_custom_colors = QtWidgets.QCheckBox("Use custom chart colors")
198        self.use_custom_colors.stateChanged.connect(self.changeCustomColors)
199        color_options_layout.addRow(self.use_custom_colors)
200
201        self.btn_background_picker = QtWidgets.QPushButton("█")
202        self.btn_background_picker.setFixedWidth(20)
203        self.btn_background_picker.clicked.connect(
204            lambda: self.setColor(
205                "background",
206                QtWidgets.QColorDialog.getColor(
207                    self.backgroundColor,
208                    options=QtWidgets.QColorDialog.ShowAlphaChannel)))
209
210        color_options_layout.addRow(
211            "Chart background", self.btn_background_picker)
212
213        self.btn_foreground_picker = QtWidgets.QPushButton("█")
214        self.btn_foreground_picker.setFixedWidth(20)
215        self.btn_foreground_picker.clicked.connect(
216            lambda: self.setColor(
217                "foreground",
218                QtWidgets.QColorDialog.getColor(
219                    self.foregroundColor,
220                    options=QtWidgets.QColorDialog.ShowAlphaChannel)))
221
222        color_options_layout.addRow("Chart foreground", self.btn_foreground_picker)
223
224        self.btn_text_picker = QtWidgets.QPushButton("█")
225        self.btn_text_picker.setFixedWidth(20)
226        self.btn_text_picker.clicked.connect(
227            lambda: self.setColor(
228                "text",
229                QtWidgets.QColorDialog.getColor(
230                    self.textColor,
231                    options=QtWidgets.QColorDialog.ShowAlphaChannel)))
232
233        color_options_layout.addRow("Chart text", self.btn_text_picker)
234
235        right_layout = QtWidgets.QVBoxLayout()
236        layout.addLayout(right_layout)
237
238        font_options_box = QtWidgets.QGroupBox("Font")
239        font_options_layout = QtWidgets.QFormLayout(font_options_box)
240        self.font_dropdown = QtWidgets.QComboBox()
241        self.font_dropdown.addItems(["7", "8", "9", "10", "11", "12"])
242        font_size = self.app.settings.value("FontSize",
243                                            defaultValue="8",
244                                            type=str)
245        self.font_dropdown.setCurrentText(font_size)
246        self.changeFont()
247
248        self.font_dropdown.currentTextChanged.connect(self.changeFont)
249        font_options_layout.addRow("Font size", self.font_dropdown)
250
251        bands_box = QtWidgets.QGroupBox("Bands")
252        bands_layout = QtWidgets.QFormLayout(bands_box)
253
254        self.show_bands = QtWidgets.QCheckBox("Show bands")
255        self.show_bands.setChecked(self.app.bands.enabled)
256        self.show_bands.stateChanged.connect(lambda: self.setShowBands(self.show_bands.isChecked()))
257        bands_layout.addRow(self.show_bands)
258
259        self.btn_bands_picker = QtWidgets.QPushButton("█")
260        self.btn_bands_picker.setFixedWidth(20)
261        self.btn_bands_picker.clicked.connect(
262            lambda: self.setColor(
263                "bands",
264                QtWidgets.QColorDialog.getColor(
265                    self.bandsColor,
266                    options=QtWidgets.QColorDialog.ShowAlphaChannel)))
267
268        bands_layout.addRow("Chart bands", self.btn_bands_picker)
269
270        self.btn_manage_bands = QtWidgets.QPushButton("Manage bands")
271
272        self.bandsWindow = BandsWindow(self.app)
273        self.btn_manage_bands.clicked.connect(self.displayBandsWindow)
274
275        bands_layout.addRow(self.btn_manage_bands)
276
277        vswr_marker_box = QtWidgets.QGroupBox("VSWR Markers")
278        vswr_marker_layout = QtWidgets.QFormLayout(vswr_marker_box)
279
280        self.vswrMarkers: List[float] = self.app.settings.value("VSWRMarkers", [], float)
281
282        if isinstance(self.vswrMarkers, float):
283            if self.vswrMarkers == 0:
284                self.vswrMarkers = []
285            else:
286                # Single values from the .ini become floats rather than lists. Convert them.
287                self.vswrMarkers = [self.vswrMarkers]
288
289        self.btn_vswr_picker = QtWidgets.QPushButton("█")
290        self.btn_vswr_picker.setFixedWidth(20)
291        self.btn_vswr_picker.clicked.connect(
292            lambda: self.setColor(
293                "vswr",
294                QtWidgets.QColorDialog.getColor(
295                    self.vswrColor,
296                    options=QtWidgets.QColorDialog.ShowAlphaChannel)))
297
298        vswr_marker_layout.addRow("VSWR Markers", self.btn_vswr_picker)
299
300        self.vswr_marker_dropdown = QtWidgets.QComboBox()
301        vswr_marker_layout.addRow(self.vswr_marker_dropdown)
302
303        if len(self.vswrMarkers) == 0:
304            self.vswr_marker_dropdown.addItem("None")
305        else:
306            for m in self.vswrMarkers:
307                self.vswr_marker_dropdown.addItem(str(m))
308                for c in self.app.s11charts:
309                    c.addSWRMarker(m)
310
311        self.vswr_marker_dropdown.setCurrentIndex(0)
312        btn_add_vswr_marker = QtWidgets.QPushButton("Add ...")
313        btn_remove_vswr_marker = QtWidgets.QPushButton("Remove")
314        vswr_marker_btn_layout = QtWidgets.QHBoxLayout()
315        vswr_marker_btn_layout.addWidget(btn_add_vswr_marker)
316        vswr_marker_btn_layout.addWidget(btn_remove_vswr_marker)
317        vswr_marker_layout.addRow(vswr_marker_btn_layout)
318
319        btn_add_vswr_marker.clicked.connect(self.addVSWRMarker)
320        btn_remove_vswr_marker.clicked.connect(self.removeVSWRMarker)
321
322        markers_box = QtWidgets.QGroupBox("Markers")
323        markers_layout = QtWidgets.QFormLayout(markers_box)
324
325        btn_add_marker = QtWidgets.QPushButton("Add")
326        btn_add_marker.clicked.connect(self.addMarker)
327        self.btn_remove_marker = QtWidgets.QPushButton("Remove")
328        self.btn_remove_marker.clicked.connect(self.removeMarker)
329        btn_marker_settings = QtWidgets.QPushButton("Settings ...")
330        btn_marker_settings.clicked.connect(self.displayMarkerWindow)
331
332        marker_btn_layout = QtWidgets.QHBoxLayout()
333        marker_btn_layout.addWidget(btn_add_marker)
334        marker_btn_layout.addWidget(self.btn_remove_marker)
335        marker_btn_layout.addWidget(btn_marker_settings)
336
337        markers_layout.addRow(marker_btn_layout)
338
339        charts_box = QtWidgets.QGroupBox("Displayed charts")
340        charts_layout = QtWidgets.QGridLayout(charts_box)
341
342        # selections = ["S11 Smith chart",
343        #               "S11 LogMag",
344        #               "S11 VSWR",
345        #               "S11 Phase",
346        #               "S21 Smith chart",
347        #               "S21 LogMag",
348        #               "S21 Phase",
349        #               "None"]
350
351        selections = []
352
353        for c in self.app.selectable_charts:
354            selections.append(c.name)
355
356        selections.append("None")
357        chart00_selection = QtWidgets.QComboBox()
358        chart00_selection.addItems(selections)
359        chart00 = self.app.settings.value("Chart00", "S11 Smith Chart")
360        if chart00_selection.findText(chart00) > -1:
361            chart00_selection.setCurrentText(chart00)
362        else:
363            chart00_selection.setCurrentText("S11 Smith Chart")
364        chart00_selection.currentTextChanged.connect(
365            lambda: self.changeChart(0, 0, chart00_selection.currentText()))
366        charts_layout.addWidget(chart00_selection, 0, 0)
367
368        chart01_selection = QtWidgets.QComboBox()
369        chart01_selection.addItems(selections)
370        chart01 = self.app.settings.value("Chart01", "S11 Return Loss")
371        if chart01_selection.findText(chart01) > -1:
372            chart01_selection.setCurrentText(chart01)
373        else:
374            chart01_selection.setCurrentText("S11 Return Loss")
375        chart01_selection.currentTextChanged.connect(
376            lambda: self.changeChart(0, 1, chart01_selection.currentText()))
377        charts_layout.addWidget(chart01_selection, 0, 1)
378
379        chart02_selection = QtWidgets.QComboBox()
380        chart02_selection.addItems(selections)
381        chart02 = self.app.settings.value("Chart02", "None")
382        if chart02_selection.findText(chart02) > -1:
383            chart02_selection.setCurrentText(chart02)
384        else:
385            chart02_selection.setCurrentText("None")
386        chart02_selection.currentTextChanged.connect(
387            lambda: self.changeChart(0, 2, chart02_selection.currentText()))
388        charts_layout.addWidget(chart02_selection, 0, 2)
389
390        chart10_selection = QtWidgets.QComboBox()
391        chart10_selection.addItems(selections)
392        chart10 = self.app.settings.value("Chart10", "S21 Polar Plot")
393        if chart10_selection.findText(chart10) > -1:
394            chart10_selection.setCurrentText(chart10)
395        else:
396            chart10_selection.setCurrentText("S21 Polar Plot")
397        chart10_selection.currentTextChanged.connect(
398            lambda: self.changeChart(1, 0, chart10_selection.currentText()))
399        charts_layout.addWidget(chart10_selection, 1, 0)
400
401        chart11_selection = QtWidgets.QComboBox()
402        chart11_selection.addItems(selections)
403        chart11 = self.app.settings.value("Chart11", "S21 Gain")
404        if chart11_selection.findText(chart11) > -1:
405            chart11_selection.setCurrentText(chart11)
406        else:
407            chart11_selection.setCurrentText("S21 Gain")
408        chart11_selection.currentTextChanged.connect(
409            lambda: self.changeChart(1, 1, chart11_selection.currentText()))
410        charts_layout.addWidget(chart11_selection, 1, 1)
411
412        chart12_selection = QtWidgets.QComboBox()
413        chart12_selection.addItems(selections)
414        chart12 = self.app.settings.value("Chart12", "None")
415        if chart12_selection.findText(chart12) > -1:
416            chart12_selection.setCurrentText(chart12)
417        else:
418            chart12_selection.setCurrentText("None")
419        chart12_selection.currentTextChanged.connect(
420            lambda: self.changeChart(1, 2, chart12_selection.currentText()))
421        charts_layout.addWidget(chart12_selection, 1, 2)
422
423        self.changeChart(0, 0, chart00_selection.currentText())
424        self.changeChart(0, 1, chart01_selection.currentText())
425        self.changeChart(0, 2, chart02_selection.currentText())
426        self.changeChart(1, 0, chart10_selection.currentText())
427        self.changeChart(1, 1, chart11_selection.currentText())
428        self.changeChart(1, 2, chart12_selection.currentText())
429
430        self.backgroundColor = self.app.settings.value(
431            "BackgroundColor", defaultValue=QtGui.QColor("white"),
432            type=QtGui.QColor)
433        self.foregroundColor = self.app.settings.value(
434            "ForegroundColor", defaultValue=QtGui.QColor("lightgray"),
435            type=QtGui.QColor)
436        self.textColor = self.app.settings.value(
437            "TextColor", defaultValue=QtGui.QColor("black"),
438            type=QtGui.QColor)
439        self.bandsColor = self.app.settings.value(
440            "BandsColor", defaultValue=QtGui.QColor(128, 128, 128, 48),
441            type=QtGui.QColor)
442        self.app.bands.color = self.bandsColor
443        self.vswrColor = self.app.settings.value(
444            "VSWRColor", defaultValue=QtGui.QColor(192, 0, 0, 128),
445            type=QtGui.QColor)
446
447        self.dark_mode_option.setChecked(
448            self.app.settings.value("DarkMode", False, bool))
449        self.show_lines_option.setChecked(
450            self.app.settings.value("ShowLines", False, bool))
451        self.show_marker_number_option.setChecked(
452            self.app.settings.value("ShowMarkerNumbers", False, bool))
453        self.filled_marker_option.setChecked(
454            self.app.settings.value("FilledMarkers", False, bool))
455
456        if self.app.settings.value("UseCustomColors",
457                                   defaultValue=False, type=bool):
458            self.dark_mode_option.setDisabled(True)
459            self.dark_mode_option.setChecked(False)
460            self.use_custom_colors.setChecked(True)
461        else:
462            self.btn_background_picker.setDisabled(True)
463            self.btn_foreground_picker.setDisabled(True)
464            self.btn_text_picker.setDisabled(True)
465
466        self.changeCustomColors()  # Update all the colours of all the charts
467
468        p = self.btn_background_picker.palette()
469        p.setColor(QtGui.QPalette.ButtonText, self.backgroundColor)
470        self.btn_background_picker.setPalette(p)
471
472        p = self.btn_foreground_picker.palette()
473        p.setColor(QtGui.QPalette.ButtonText, self.foregroundColor)
474        self.btn_foreground_picker.setPalette(p)
475
476        p = self.btn_text_picker.palette()
477        p.setColor(QtGui.QPalette.ButtonText, self.textColor)
478        self.btn_text_picker.setPalette(p)
479
480        p = self.btn_bands_picker.palette()
481        p.setColor(QtGui.QPalette.ButtonText, self.bandsColor)
482        self.btn_bands_picker.setPalette(p)
483
484        p = self.btn_vswr_picker.palette()
485        p.setColor(QtGui.QPalette.ButtonText, self.vswrColor)
486        self.btn_vswr_picker.setPalette(p)
487
488        left_layout.addWidget(display_options_box)
489        left_layout.addWidget(charts_box)
490        left_layout.addWidget(markers_box)
491        left_layout.addStretch(1)
492
493        right_layout.addWidget(color_options_box)
494        right_layout.addWidget(font_options_box)
495        right_layout.addWidget(bands_box)
496        right_layout.addWidget(vswr_marker_box)
497        right_layout.addStretch(1)
498
499    def changeChart(self, x, y, chart):
500        found = None
501        for c in self.app.selectable_charts:
502            if c.name == chart:
503                found = c
504
505        self.app.settings.setValue("Chart" + str(x) + str(y), chart)
506
507        old_widget = self.app.charts_layout.itemAtPosition(x, y)
508        if old_widget is not None:
509            w = old_widget.widget()
510            self.app.charts_layout.removeWidget(w)
511            w.hide()
512        if found is not None:
513            if self.app.charts_layout.indexOf(found) > -1:
514                logger.debug("%s is already shown, duplicating.", found.name)
515                found = self.app.copyChart(found)
516
517            self.app.charts_layout.addWidget(found, x, y)
518            if found.isHidden():
519                found.show()
520
521    def changeReturnLoss(self):
522        state = self.returnloss_is_positive.isChecked()
523        self.app.settings.setValue("ReturnLossPositive", state)
524
525        for m in self.app.markers:
526            m.returnloss_is_positive = state
527            m.updateLabels(self.app.data11, self.app.data21)
528        self.marker_window.exampleMarker.returnloss_is_positive = state
529        self.marker_window.updateMarker()
530        self.app.charts["s11"]["log_mag"].isInverted = state
531        self.app.charts["s11"]["log_mag"].update()
532
533    def changeShowLines(self):
534        state = self.show_lines_option.isChecked()
535        self.app.settings.setValue("ShowLines", state)
536        for c in self.app.subscribing_charts:
537            c.setDrawLines(state)
538
539    def changeShowMarkerNumber(self):
540        state = self.show_marker_number_option.isChecked()
541        self.app.settings.setValue("ShowMarkerNumbers", state)
542        for c in self.app.subscribing_charts:
543            c.setDrawMarkerNumbers(state)
544
545    def changeFilledMarkers(self):
546        state = self.filled_marker_option.isChecked()
547        self.app.settings.setValue("FilledMarkers", state)
548        for c in self.app.subscribing_charts:
549            c.setFilledMarkers(state)
550
551    def changeMarkerAtTip(self):
552        state = self.marker_at_tip.isChecked()
553        self.app.settings.setValue("MarkerAtTip", state)
554        for c in self.app.subscribing_charts:
555            c.setMarkerAtTip(state)
556
557    def changePointSize(self, size: int):
558        self.app.settings.setValue("PointSize", size)
559        for c in self.app.subscribing_charts:
560            c.setPointSize(size)
561
562    def changeLineThickness(self, size: int):
563        self.app.settings.setValue("LineThickness", size)
564        for c in self.app.subscribing_charts:
565            c.setLineThickness(size)
566
567    def changeMarkerSize(self, size: int):
568        if size % 2 == 0:
569            self.app.settings.setValue("MarkerSize", size)
570            for c in self.app.subscribing_charts:
571                c.setMarkerSize(int(size / 2))
572
573    def validateMarkerSize(self):
574        size = self.markerSizeInput.value()
575        if size % 2 != 0:
576            self.markerSizeInput.setValue(size + 1)
577
578    def changeDarkMode(self):
579        state = self.dark_mode_option.isChecked()
580        self.app.settings.setValue("DarkMode", state)
581        if state:
582            for c in self.app.subscribing_charts:
583                c.setBackgroundColor(QtGui.QColor(QtCore.Qt.black))
584                c.setForegroundColor(QtGui.QColor(QtCore.Qt.lightGray))
585                c.setTextColor(QtGui.QColor(QtCore.Qt.white))
586                c.setSWRColor(self.vswrColor)
587        else:
588            for c in self.app.subscribing_charts:
589                c.setBackgroundColor(QtGui.QColor(QtCore.Qt.white))
590                c.setForegroundColor(QtGui.QColor(QtCore.Qt.lightGray))
591                c.setTextColor(QtGui.QColor(QtCore.Qt.black))
592                c.setSWRColor(self.vswrColor)
593
594    def changeCustomColors(self):
595        self.app.settings.setValue("UseCustomColors", self.use_custom_colors.isChecked())
596        if self.use_custom_colors.isChecked():
597            self.dark_mode_option.setDisabled(True)
598            self.dark_mode_option.setChecked(False)
599            self.btn_background_picker.setDisabled(False)
600            self.btn_foreground_picker.setDisabled(False)
601            self.btn_text_picker.setDisabled(False)
602            for c in self.app.subscribing_charts:
603                c.setBackgroundColor(self.backgroundColor)
604                c.setForegroundColor(self.foregroundColor)
605                c.setTextColor(self.textColor)
606                c.setSWRColor(self.vswrColor)
607        else:
608            self.dark_mode_option.setDisabled(False)
609            self.btn_background_picker.setDisabled(True)
610            self.btn_foreground_picker.setDisabled(True)
611            self.btn_text_picker.setDisabled(True)
612            self.changeDarkMode()  # Reset to the default colors depending on Dark Mode setting
613
614    def setColor(self, name: str, color: QtGui.QColor):
615        if name == "background":
616            p = self.btn_background_picker.palette()
617            p.setColor(QtGui.QPalette.ButtonText, color)
618            self.btn_background_picker.setPalette(p)
619            self.backgroundColor = color
620            self.app.settings.setValue("BackgroundColor", color)
621        elif name == "foreground":
622            p = self.btn_foreground_picker.palette()
623            p.setColor(QtGui.QPalette.ButtonText, color)
624            self.btn_foreground_picker.setPalette(p)
625            self.foregroundColor = color
626            self.app.settings.setValue("ForegroundColor", color)
627        elif name == "text":
628            p = self.btn_text_picker.palette()
629            p.setColor(QtGui.QPalette.ButtonText, color)
630            self.btn_text_picker.setPalette(p)
631            self.textColor = color
632            self.app.settings.setValue("TextColor", color)
633        elif name == "bands":
634            p = self.btn_bands_picker.palette()
635            p.setColor(QtGui.QPalette.ButtonText, color)
636            self.btn_bands_picker.setPalette(p)
637            self.bandsColor = color
638            self.app.settings.setValue("BandsColor", color)
639            self.app.bands.setColor(color)
640        elif name == "vswr":
641            p = self.btn_vswr_picker.palette()
642            p.setColor(QtGui.QPalette.ButtonText, color)
643            self.btn_vswr_picker.setPalette(p)
644            self.vswrColor = color
645            self.app.settings.setValue("VSWRColor", color)
646        self.changeCustomColors()
647
648    def setSweepColor(self, color: QtGui.QColor):
649        if color.isValid():
650            self.sweepColor = color
651            p = self.btnColorPicker.palette()
652            p.setColor(QtGui.QPalette.ButtonText, color)
653            self.btnColorPicker.setPalette(p)
654            self.app.settings.setValue("SweepColor", color)
655            self.app.settings.sync()
656            for c in self.app.subscribing_charts:
657                c.setSweepColor(color)
658
659    def setSecondarySweepColor(self, color: QtGui.QColor):
660        if color.isValid():
661            self.secondarySweepColor = color
662            p = self.btnSecondaryColorPicker.palette()
663            p.setColor(QtGui.QPalette.ButtonText, color)
664            self.btnSecondaryColorPicker.setPalette(p)
665            self.app.settings.setValue("SecondarySweepColor", color)
666            self.app.settings.sync()
667            for c in self.app.subscribing_charts:
668                c.setSecondarySweepColor(color)
669
670    def setReferenceColor(self, color):
671        if color.isValid():
672            self.referenceColor = color
673            p = self.btnReferenceColorPicker.palette()
674            p.setColor(QtGui.QPalette.ButtonText, color)
675            self.btnReferenceColorPicker.setPalette(p)
676            self.app.settings.setValue("ReferenceColor", color)
677            self.app.settings.sync()
678
679            for c in self.app.subscribing_charts:
680                c.setReferenceColor(color)
681
682    def setSecondaryReferenceColor(self, color):
683        if color.isValid():
684            self.secondaryReferenceColor = color
685            p = self.btnSecondaryReferenceColorPicker.palette()
686            p.setColor(QtGui.QPalette.ButtonText, color)
687            self.btnSecondaryReferenceColorPicker.setPalette(p)
688            self.app.settings.setValue("SecondaryReferenceColor", color)
689            self.app.settings.sync()
690
691            for c in self.app.subscribing_charts:
692                c.setSecondaryReferenceColor(color)
693
694    def setShowBands(self, show_bands):
695        self.app.bands.enabled = show_bands
696        self.app.bands.settings.setValue("ShowBands", show_bands)
697        self.app.bands.settings.sync()
698        for c in self.app.subscribing_charts:
699            c.update()
700
701    def changeFont(self):
702        font_size = self.font_dropdown.currentText()
703        self.app.settings.setValue("FontSize", font_size)
704        app: QtWidgets.QApplication = QtWidgets.QApplication.instance()
705        font = app.font()
706        font.setPointSize(int(font_size))
707        app.setFont(font)
708        self.app.changeFont(font)
709
710    def displayBandsWindow(self):
711        self.bandsWindow.show()
712        QtWidgets.QApplication.setActiveWindow(self.bandsWindow)
713
714    def displayMarkerWindow(self):
715        self.marker_window.show()
716        QtWidgets.QApplication.setActiveWindow(self.marker_window)
717
718    def addMarker(self):
719        new_marker = Marker("", self.app.settings)
720        new_marker.setScale(self.app.scaleFactor)
721        self.app.markers.append(new_marker)
722        self.app.marker_data_layout.addWidget(new_marker.get_data_layout())
723        self.app.marker_frame.adjustSize()
724
725        new_marker.updated.connect(self.app.markerUpdated)
726        label, layout = new_marker.getRow()
727        self.app.marker_control.layout.insertRow(Marker.count() - 1, label, layout)
728        self.btn_remove_marker.setDisabled(False)
729
730        if Marker.count() >= 2:
731            self.app.marker_control.check_delta.setDisabled(False)
732
733    def removeMarker(self):
734        # keep at least one marker
735        if Marker.count() <= 1:
736            return
737        if Marker.count() == 2:
738            self.btn_remove_marker.setDisabled(True)
739            self.app.delta_marker_layout.setVisible(False)
740            self.app.marker_control.check_delta.setDisabled(True)
741        last_marker = self.app.markers.pop()
742
743        last_marker.updated.disconnect(self.app.markerUpdated)
744        self.app.marker_data_layout.removeWidget(last_marker.get_data_layout())
745        self.app.marker_control.layout.removeRow(Marker.count()-1)
746        self.app.marker_frame.adjustSize()
747
748        last_marker.get_data_layout().hide()
749        last_marker.get_data_layout().destroy()
750        label, _ = last_marker.getRow()
751        label.hide()
752
753    def addVSWRMarker(self):
754        value, selected = QtWidgets.QInputDialog.getDouble(
755            self, "Add VSWR Marker", "VSWR value to show:", min=1.001, decimals=3)
756        if selected:
757            self.vswrMarkers.append(value)
758            if self.vswr_marker_dropdown.itemText(0) == "None":
759                self.vswr_marker_dropdown.removeItem(0)
760            self.vswr_marker_dropdown.addItem(str(value))
761            self.vswr_marker_dropdown.setCurrentText(str(value))
762            for c in self.app.s11charts:
763                c.addSWRMarker(value)
764            self.app.settings.setValue("VSWRMarkers", self.vswrMarkers)
765
766    def removeVSWRMarker(self):
767        value_str = self.vswr_marker_dropdown.currentText()
768        if value_str != "None":
769            value = float(value_str)
770            self.vswrMarkers.remove(value)
771            self.vswr_marker_dropdown.removeItem(self.vswr_marker_dropdown.currentIndex())
772            if self.vswr_marker_dropdown.count() == 0:
773                self.vswr_marker_dropdown.addItem("None")
774                self.app.settings.remove("VSWRMarkers")
775            else:
776                self.app.settings.setValue("VSWRMarkers", self.vswrMarkers)
777            for c in self.app.s11charts:
778                c.removeSWRMarker(value)
779