Skip to content
Snippets Groups Projects

Implement dialog to add/edit a single channel in database

Merged Lan Dam requested to merge i69-add-edit-single-channel-dialog into master
1 file
+ 5
3
Compare changes
  • Side-by-side
  • Inline
import sys
import platform
import os
from typing import Optional, Dict
from PySide2 import QtWidgets, QtGui
from PySide2.QtWidgets import QWidget, QDialog
from sohstationviewer.database.process_db import execute_db
from sohstationviewer.database.extract_data import (
get_params, get_channel_info, create_assign_string_for_db_query
)
from sohstationviewer.view.db_config.edit_single_param_dialog import \
EditSingleParamDialog
from sohstationviewer.conf.dbSettings import modify_db_path
def add_separation_line(layout):
"""
Add a line for separation to the given layout.
:param layout: QLayout - the layout that contains the line
"""
label = QtWidgets.QLabel()
label.setFrameStyle(QtWidgets.QFrame.HLine | QtWidgets.QFrame.Sunken)
label.setLineWidth(1)
layout.addWidget(label)
class AddEditSingleChannelDialog(QDialog):
"""
Dialog to add info for channel not in database or edit the existing channel
"""
def __init__(self, parent: Optional[QWidget],
chan_id: str, data_type: str):
"""
:param parent: the parent widget
:param chan_id: name of channel to be added/edited
:param data_type: type of the data being processed
"""
self.parent = parent
# name of the channel
self.chan_id = chan_id
# data_type of the channel
self.data_type = data_type
# param of the channel
self.param: str = 'Default'
# True if this channel isn't in DB yet
self.is_new_db_channel: bool = False
# To skip on_param_chkbox_changed() when param is changed by the
# program at the beginning
self.param_changed_by_signal: bool = False
# database info of the channel
self.channel_info: Dict = {}
# database info of the channel's parameter
self.param_info: Dict = {}
super(AddEditSingleChannelDialog, self).__init__(parent)
# short name of the channel
self.channel_name_lnedit = QtWidgets.QLineEdit(self)
self.channel_name_lnedit.setReadOnly(True)
# description added to channel name
self.label_lnedit = QtWidgets.QLineEdit(self)
self.label_lnedit.setPlaceholderText(
"added to channel name to be displayed")
# convert factor to change from count to actual value
self.conversion_lnedit = QtWidgets.QLineEdit(self)
self.conversion_lnedit.setPlaceholderText(
"to convert from count to actual value"
)
validator = QtGui.QDoubleValidator(0.0, 5.0, 6)
validator.setNotation(QtGui.QDoubleValidator.StandardNotation)
self.conversion_lnedit.setValidator(validator)
self.conversion_lnedit.setText('1')
# channel's unit
self.unit_lnedit = QtWidgets.QLineEdit(self)
# dedimal point for channel's value
self.fix_point_spnbox = QtWidgets.QSpinBox()
self.fix_point_spnbox.setToolTip("Decimal point that allow in display")
self.fix_point_spnbox.setMinimum(0)
self.fix_point_spnbox.setMaximum(5)
# data_type
self.data_type_lnedit = QtWidgets.QLineEdit(self)
self.data_type_lnedit.setReadOnly(True)
# channel's parameter which decides how channel is plotted
self.param_cbobox = QtWidgets.QComboBox(self)
self.param_cbobox.addItems(get_params())
# button to edit param
self.edit_param_btn = QtWidgets.QPushButton("EDIT PARAMETER", self)
# button to save changes to DB
self.save_btn = QtWidgets.QPushButton("SAVE CHANNEL", self)
# button to save changes and replot channel
self.save_replot_btn = QtWidgets.QPushButton("SAVE & REPLOT", self)
# button to close dialog without doing anything
self.cancel_btn = QtWidgets.QPushButton('CANCEL', self)
self.setup_ui()
self.set_channel_info()
self.connect_signals()
def setup_ui(self) -> None:
dlg_type = 'Add' if 'DEFAULT' in self.chan_id else 'Edit'
self.setWindowTitle(f"{dlg_type} channel {self.chan_id}"
f" - {self.data_type}")
main_layout = QtWidgets.QVBoxLayout()
self.setLayout(main_layout)
instruction = (
f"This dialog is to {dlg_type} channel {self.chan_id}.\n"
"Parameter need to be any value different than 'Default' to be "
"saved.")
main_layout.addWidget(QtWidgets.QLabel(instruction))
channel_layout = QtWidgets.QGridLayout()
main_layout.addLayout(channel_layout)
channel_layout.addWidget(QtWidgets.QLabel('Name'), 0, 0, 1, 1)
channel_layout.addWidget(self.channel_name_lnedit, 0, 1, 1, 1)
channel_layout.addWidget(QtWidgets.QLabel('Label'), 1, 0, 1, 1)
channel_layout.addWidget(self.label_lnedit, 1, 1, 1, 1)
channel_layout.addWidget(QtWidgets.QLabel('Conversion'), 2, 0, 1, 1)
channel_layout.addWidget(self.conversion_lnedit, 2, 1, 1, 1)
channel_layout.addWidget(QtWidgets.QLabel('Unit'), 3, 0, 1, 1)
channel_layout.addWidget(self.unit_lnedit, 3, 1, 1, 1)
channel_layout.addWidget(QtWidgets.QLabel('Fix Point'), 4, 0, 1, 1)
channel_layout.addWidget(self.fix_point_spnbox, 4, 1, 1, 1)
channel_layout.addWidget(QtWidgets.QLabel('Data Type'), 5, 0, 1, 1)
channel_layout.addWidget(self.data_type_lnedit, 5, 1, 1, 1)
channel_layout.addWidget(QtWidgets.QLabel('Parameter'), 6, 0, 1, 1)
channel_layout.addWidget(self.param_cbobox, 6, 1, 1, 1)
channel_layout.addWidget(self.save_btn, 7, 0, 1, 1)
channel_layout.addWidget(self.save_replot_btn, 7, 1, 1, 1)
channel_layout.addWidget(self.edit_param_btn, 8, 1, 1, 1)
channel_layout.addWidget(self.cancel_btn, 8, 0, 1, 1)
self.save_replot_btn.setFocus()
def connect_signals(self) -> None:
self.param_cbobox.currentTextChanged.connect(
self.on_param_cbobox_changed)
self.cancel_btn.clicked.connect(self.close)
self.save_btn.clicked.connect(self.on_save)
self.save_replot_btn.clicked.connect(self.on_save_replot)
self.edit_param_btn.clicked.connect(self.on_edit_param)
def set_channel_info(self):
"""
Add all Channel related info according to information got from DB.
In case Channel isn't in the DB, use the info of DEFAULT channel.
Call set_param_info to set Parameter related info.
"""
try:
self.channel_info = get_channel_info(self.chan_id, self.data_type)
except IndexError:
self.is_new_db_channel = True
self.channel_info = get_channel_info('DEFAULT', 'Default')
self.channel_name_lnedit.setText(self.chan_id)
self.label_lnedit.setText(self.channel_info['label'])
self.conversion_lnedit.setText(
str(float(self.channel_info['convertFactor'])))
self.unit_lnedit.setText(self.channel_info['unit'])
if self.channel_info['fixPoint'] is not None:
self.fix_point_spnbox.setValue(self.channel_info['fixPoint'])
self.data_type_lnedit.setText(self.data_type)
self.param_cbobox.setCurrentText(self.channel_info['param'])
self.param = self.channel_info['param']
self.set_buttons_enabled()
def on_param_cbobox_changed(self):
"""
+ Check self.param_changed_by_signal to make sure the signal come from
user selecting a parameter from param_cbobox, not the signal from
changing back to original value when condition not pass fo the set
value
+ Not allow parameter 'Default' to be select because it is only the
parameter for the channel that has no record in DB
+ If the channel already has a record in DB, give a warning when user's
trying to change its parameter.
"""
if self.param_changed_by_signal:
self.param_changed_by_signal = False
return
new_param = self.param_cbobox.currentText()
if new_param == 'Default':
# Parameter Default is only for channel that has no record in DB.
# So it isn't allowed to be selected
self.param_changed_by_signal = True
self.param_cbobox.setCurrentText(self.param)
return
if not self.is_new_db_channel:
msg = ("ARE YOU SURE YOU WANT TO CHANGE PARAMETER FOR CHANNEL "
f"'{self.chan_id}'?")
result = QtWidgets.QMessageBox.question(
self, "Confirmation", msg,
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
if result == QtWidgets.QMessageBox.No:
self.param_changed_by_signal = True
self.param_cbobox.setCurrentText(self.param)
return
self.param = new_param
self.set_buttons_enabled()
def save(self):
"""
Save info from GUI to DB
"""
if self.is_new_db_channel:
self.insert_channel_info()
else:
self.update_channel_info()
def on_save(self):
"""
Save new channel info to DB
"""
self.save()
self.close()
def on_save_replot(self):
"""
Save new channel info to DB
TODO: Replot the channel in the plotting area
"""
self.save()
print("Do REPLOT")
self.close()
def set_buttons_enabled(self):
"""
Disable the 3 buttons to save and to edit parameters so that user are
forced to change param before they want to continue.
"""
if self.param == 'Default':
self.edit_param_btn.setEnabled(False)
self.save_btn.setEnabled(False)
self.save_replot_btn.setEnabled(False)
else:
self.edit_param_btn.setEnabled(True)
self.save_btn.setEnabled(True)
self.save_replot_btn.setEnabled(True)
def on_edit_param(self):
"""
Give user a warning when they want to change parameter's info then
open EditSingleParamDialog for user to edit parameter's info after
they give their confirmation.
"""
msg = ("Changing parameter will affect all of other channels that "
"have the same parameter.\n\n"
"Are you sure you want to continue?")
result = QtWidgets.QMessageBox.question(
self, "Confirmation", msg,
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
if result == QtWidgets.QMessageBox.No:
return
win = EditSingleParamDialog(self, self.param_cbobox.currentText())
win.exec_()
def update_para_info(self, param):
"""
Save parameter related info to Parameters table
:param param: param condition string
"""
plot_type = create_assign_string_for_db_query(
'plotType', self.plot_type_cbo_box.currentText())
value_colorb = create_assign_string_for_db_query(
'valueColorsB', self.value_colorb_widget.text())
value_colorw = create_assign_string_for_db_query(
'valueColorsW', self.value_colorw_widget.text())
height = f"height={self.height_spnbox.value()}"
sql = (f"UPDATE Parameters SET {plot_type}, {value_colorb}, "
f"{value_colorw}, {height} WHERE {param}")
execute_db(sql)
def insert_channel_info(self):
sql = ("INSERT INTO Channels VALUES ("
f"'{self.channel_name_lnedit.text()}', "
f"'{self.label_lnedit.text()}', "
f"'{self.param_cbobox.currentText()}', "
f"NULL, " # linkedChan for RT130 only and won't be changed
f"{self.conversion_lnedit.text()}, "
f"'{self.unit_lnedit.text()}', "
f"{self.fix_point_spnbox.value()}, "
f"'{self.data_type_lnedit.text()}')")
execute_db(sql)
def update_channel_info(self):
channel = f"channel='{self.channel_name_lnedit.text()}'"
label = f"label='{self.label_lnedit.text()}'"
param = f"param='{self.param_cbobox.currentText()}'"
linked_chan = "linkedChan=NULL"
convert_factor = f"convertFactor={self.conversion_lnedit.text()}"
unit = f"unit='{self.unit_lnedit.text()}'"
fix_point = f"fixPoint={self.fix_point_spnbox.value()}"
data_type = f"dataType='{self.data_type_lnedit.text()}'"
sql = (f"UPDATE Channels SET {label}, {param}, {linked_chan}, "
f"{convert_factor}, {unit}, {fix_point}, {data_type} "
f"WHERE {channel}")
execute_db(sql)
if __name__ == '__main__':
modify_db_path()
os_name, version, *_ = platform.platform().split('-')
if os_name == 'macOS':
os.environ['QT_MAC_WANTS_LAYER'] = '1'
app = QtWidgets.QApplication(sys.argv)
# test new channel
# test = AddEditSingleChannelDialog(None, 'VEE', 'Q330')
# test linesDots. Ex: param: Input power supply current
# test = AddEditSingleChannelDialog(None, 'VEC', 'Q330')
# test MultiColorDotsLowerBound. Ex: param:Backup volt
# test = AddEditSingleChannelDialog(None, 'Backup Volt', 'RT130')
# test MultiColorDotsUpperBound. Ex: param:GNSS status
test = AddEditSingleChannelDialog(None, 'VST', 'Pegasus')
# test UpDownDots. Ex: param. Ex: param:Net Up/down
# test = AddEditSingleChannelDialog(None, 'Net Up/Down', 'RT130')
# test TriColorLInes. Ex: param. Ex: param:Error/warning
# test = AddEditSingleChannelDialog(None, 'Error/Warning', 'RT130')
test.exec_()
sys.exit(app.exec_())
Loading