Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • software_public/passoft/sohstationviewer
1 result
Show changes
Commits on Source (6)
Showing
with 233 additions and 42 deletions
...@@ -6,3 +6,8 @@ History ...@@ -6,3 +6,8 @@ History
-------- --------
* First release * First release
2023.1.0.1
--------
* Fixed a problem with SOHViewer not fitting on smaller resolutions
package: package:
name: sohviewer name: sohviewer
version: 2023.1.0.0 version: 2023.1.0.1
source: source:
path: ../ path: ../
......
...@@ -51,6 +51,6 @@ setup( ...@@ -51,6 +51,6 @@ setup(
name='sohstationviewer', name='sohstationviewer',
packages=find_packages(include=['sohstationviewer*']), packages=find_packages(include=['sohstationviewer*']),
url='https://git.passcal.nmt.edu/software_public/passoft/sohstationviewer', url='https://git.passcal.nmt.edu/software_public/passoft/sohstationviewer',
version='2023.1.0.0', version='2023.1.0.1',
zip_safe=False, zip_safe=False,
) )
from typing import Literal from typing import Literal
# The current version of SOHStationViewer # The current version of SOHStationViewer
SOFTWARE_VERSION = '2023.1.0.0' SOFTWARE_VERSION = '2023.1.0.1'
# waveform pattern # waveform pattern
WF_1ST = 'A-HLM-V' WF_1ST = 'A-HLM-V'
......
sohstationviewer/images/edit_icon_black_background.png

1.14 KiB

sohstationviewer/images/edit_icon_white_background.png

7.12 KiB

...@@ -6,6 +6,7 @@ import traceback ...@@ -6,6 +6,7 @@ import traceback
from pathlib import Path from pathlib import Path
from PySide2 import QtWidgets from PySide2 import QtWidgets
from PySide2.QtGui import QGuiApplication
from PySide2.QtWidgets import QMessageBox from PySide2.QtWidgets import QMessageBox
from sohstationviewer.view.main_window import MainWindow from sohstationviewer.view.main_window import MainWindow
...@@ -14,7 +15,6 @@ from sohstationviewer.conf.config_processor import ( ...@@ -14,7 +15,6 @@ from sohstationviewer.conf.config_processor import (
BadConfigError, BadConfigError,
) )
# Enable Layer-backing for MacOs version >= 11 # Enable Layer-backing for MacOs version >= 11
# Only needed if using the pyside2 library with version>=5.15. # Only needed if using the pyside2 library with version>=5.15.
# Layer-backing is always enabled in pyside6. # Layer-backing is always enabled in pyside6.
...@@ -26,47 +26,91 @@ if os_name == 'macOS': ...@@ -26,47 +26,91 @@ if os_name == 'macOS':
os.environ['QT_MAC_WANTS_LAYER'] = '1' os.environ['QT_MAC_WANTS_LAYER'] = '1'
def main(): def fix_relative_paths() -> None:
# Change the working directory so that relative paths work correctly. """
Change the working directory so that the relative paths in the code work
correctly.
"""
current_file_path = os.path.abspath(__file__) current_file_path = os.path.abspath(__file__)
current_file_dir = Path(current_file_path).parent current_file_dir = Path(current_file_path).parent
os.chdir(current_file_dir) os.chdir(current_file_dir)
def resize_windows(main_window: MainWindow):
"""
Resize the plotting windows in the program so that they fit well on all
screen resolutions.
"""
screen_size = QtWidgets.QApplication.primaryScreen().size().toTuple()
screen_width, screen_height = screen_size
main_window.resize(screen_width * 1, screen_height * 1)
main_window.waveform_dlg.resize(screen_width * (2 / 3),
screen_height * (2 / 3))
main_window.tps_dlg.resize(screen_width * (2 / 3), screen_height * (2 / 3))
main_right_x = (main_window.x() + main_window.frameSize().width())
# This offset is based on the hard-coded geometry previously assigned to
# the waveform and TPS dialogs
wf_tps_x_offset = 50
# We are moving the TPS dialog so that it is slightly offset from the right
# edge of the main window
tps_dlg_x = main_right_x - main_window.tps_dlg.width() - wf_tps_x_offset
wf_tps_y = 50
main_window.waveform_dlg.move(wf_tps_x_offset, wf_tps_y)
main_window.tps_dlg.move(tps_dlg_x, wf_tps_y)
gps_dlg_y = main_window.height() / 5
main_window.gps_dialog.move(main_window.gps_dialog.y(), gps_dlg_y)
def check_if_user_want_to_reset_config() -> bool:
"""
Show a dialog asking the user if they want to reset the config.
:return: whether the user wants to reset the config.
"""
bad_config_dialog = QMessageBox()
bad_config_dialog.setText('Something went wrong when reading the '
'config.')
bad_config_dialog.setDetailedText(traceback.format_exc())
bad_config_dialog.setInformativeText('Do you want to reset the config '
'file?')
bad_config_dialog.setStandardButtons(QMessageBox.Ok |
QMessageBox.Close)
bad_config_dialog.setDefaultButton(QMessageBox.Ok)
bad_config_dialog.setIcon(QMessageBox.Critical)
reset_choice = bad_config_dialog.exec_()
return reset_choice == QMessageBox.Ok
def main():
# Change the working directory so that relative paths work correctly.
fix_relative_paths()
app = QtWidgets.QApplication(sys.argv) app = QtWidgets.QApplication(sys.argv)
wnd = MainWindow() wnd = MainWindow()
config = ConfigProcessor() config = ConfigProcessor()
config.load_config() config.load_config()
need_reset = False do_reset = None
try: try:
config.validate_config() config.validate_config()
config.apply_config(wnd) config.apply_config(wnd)
except (BadConfigError, ValueError) as e: except (BadConfigError, ValueError) as e:
bad_config_dialog = QMessageBox() do_reset = check_if_user_want_to_reset_config()
bad_config_dialog.setText('Something went wrong when reading the ' if do_reset:
'config.')
bad_config_dialog.setDetailedText(traceback.format_exc())
bad_config_dialog.setInformativeText('Do you want to reset the config '
'file?')
bad_config_dialog.setStandardButtons(QMessageBox.Ok |
QMessageBox.Close)
bad_config_dialog.setDefaultButton(QMessageBox.Ok)
bad_config_dialog.setIcon(QMessageBox.Critical)
reset_choice = bad_config_dialog.exec_()
if reset_choice == QMessageBox.Ok:
need_reset = True
else:
sys.exit(1)
if need_reset:
try: try:
config.reset() config.reset()
except OSError: except OSError:
QMessageBox.critical(None, 'Cannot reset config', QMessageBox.critical(None, 'Cannot reset config',
'Config file cannot be reset. Please ' 'Config file cannot be reset. Please ensure '
'ensure that it is not opened in another ' 'that it is not opened in another program.',
'program.',
QMessageBox.Close) QMessageBox.Close)
sys.exit(1) sys.exit(1)
elif do_reset is not None:
sys.exit(1)
config.apply_config(wnd) config.apply_config(wnd)
resize_windows(wnd)
wnd.show() wnd.show()
sys.exit(app.exec_()) sys.exit(app.exec_())
......
import sys
import platform
import os
from pathlib import Path
from typing import Optional
from PySide2 import QtWidgets, QtGui, QtCore
from PySide2.QtCore import Qt
from PySide2.QtWidgets import QWidget, QDialog, QTextEdit
from sohstationviewer.view.db_config.value_color_helper.functions import \
convert_value_color_str, prepare_value_color_html
class ValueColorWidget(QTextEdit):
def __init__(self, parent: Optional[QWidget], background: str):
"""
Widget to display valueColors and call a dialog to edit tha value
:param parent: the parent widget
:param background: 'B'/'W': flag indicating background color
"""
QtWidgets.QTextEdit.__init__(self, parent)
self.set_background(background)
# string for value color to be saved in DB
self.value_color_str: str = ''
# dialog that pop up when clicking on edit_button to help edit color
# and value
self.edit_value_color_dialog: Optional[QWidget] = None
# type of channel's plot
self.plot_type: str = ''
self.setReadOnly(True)
# change cursor to Arrow so user know they can't edit directly
self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
# to see all info
self.setFixedHeight(28)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.verticalScrollBar().setDisabled(True)
self.edit_button = QtWidgets.QToolButton(self)
self.edit_button.setCursor(Qt.PointingHandCursor)
current_file_path = os.path.abspath(__file__)
root_path = Path(current_file_path).parent.parent.parent.parent
if background == 'B':
img_file = f"{root_path}/images/edit_icon_black_background.png"
else:
img_file = f"{root_path}/images/edit_icon_white_background.png"
self.edit_button.setIcon(QtGui.QIcon(img_file))
self.edit_button.setStyleSheet(
"background: transparent; border: none;")
self.edit_button.clicked.connect(self.on_edit)
layout = QtWidgets.QHBoxLayout(self)
layout.addWidget(self.edit_button, 0, Qt.AlignRight)
layout.setSpacing(0)
layout.setMargin(5)
def set_background(self, background: str):
"""
Set black background for user to have better feeling how the colors
displayed on black background. Text and PlaceholderText's colors
have to be changed to be readable on the black background too.
:param background: 'B'/'W': sign for background color
"""
palette = self.palette()
if background == 'B':
palette.setColor(QtGui.QPalette.Text, Qt.white)
palette.setColor(QtGui.QPalette.Base, Qt.black)
palette.setColor(QtGui.QPalette.PlaceholderText, Qt.lightGray)
self.setPalette(palette)
def set_value_color(self, plot_type: str, value_color_str: str) \
-> None:
"""
Set value_color_str, value_color_edit_dialog and display value color
string in html to show color for user to have the feeling.
:param plot_type: type of channel's plot
:param value_color_str: string for value color to be saved in DB
"""
self.plot_type = plot_type
# Won't need to convert after database's valueColors are changed
self.value_color_str = convert_value_color_str(
plot_type, value_color_str)
value_color_html = prepare_value_color_html(self.value_color_str)
self.setHtml(value_color_html)
def on_edit(self):
print('edit value color')
class TestDialog(QDialog):
def __init__(self):
super(TestDialog, self).__init__(None)
main_layout = QtWidgets.QVBoxLayout()
self.setLayout(main_layout)
self.value_colorb_widget = ValueColorWidget(self, 'B')
main_layout.addWidget(self.value_colorb_widget)
self.value_colorw_widget = ValueColorWidget(self, 'W')
main_layout.addWidget(self.value_colorw_widget)
# linesDots
self.value_colorb_widget.set_value_color('linesDots', 'L:R|D:G')
self.value_colorw_widget.set_value_color('linesDots', 'L:R|D:G')
# triColorLines
# self.value_colorb_widget.set_value_color(
# 'triColorLines', '-1:M|0:R|1:G')
# self.value_colorw_widget.set_value_color(
# 'triColorLines', '-1:M|0:R|1:G')
# multiColorDotsEqualOnUpperBound
# self.value_colorb_widget.set_value_color(
# 'multiColorDotsEqualOnUpperBound', '0:R|1:Y|2:G|+2:M')
# self.value_colorw_widget.set_value_color(
# 'multiColorDotsEqualOnUpperBound', '0:R|1:Y|2:G|+2:M')
# multiColorDotsEqualOnLowerBound
# self.value_colorb_widget.set_value_color('multiColorDotsEqualOnLowerBound',
# '3:R|3.3:Y|=3.3:G')
# self.value_colorw_widget.set_value_color('multiColorDotsEqualOnLowerBound',
# '3:R|3.3:Y|=3.3:G')
if __name__ == '__main__':
os_name, version, *_ = platform.platform().split('-')
if os_name == 'macOS':
os.environ['QT_MAC_WANTS_LAYER'] = '1'
app = QtWidgets.QApplication(sys.argv)
test = TestDialog()
test.exec_()
sys.exit(app.exec_())
...@@ -3,7 +3,7 @@ import sys ...@@ -3,7 +3,7 @@ import sys
import os import os
import traceback import traceback
from pathlib import Path from pathlib import Path
from typing import List, Optional, Literal, Iterable from typing import List, Optional, Literal, Iterable, Any
from PySide2 import QtWidgets, QtCore from PySide2 import QtWidgets, QtCore
from matplotlib.axes import Axes from matplotlib.axes import Axes
...@@ -31,7 +31,7 @@ class GPSWidget(QtWidgets.QWidget): ...@@ -31,7 +31,7 @@ class GPSWidget(QtWidgets.QWidget):
# one point for each coordinate. # one point for each coordinate.
self.unique_gps_points: Optional[List[GPSPoint]] = None self.unique_gps_points: Optional[List[GPSPoint]] = None
self.fig = Figure(figsize=(6, 6), dpi=100) self.fig = Figure(figsize=(6, 6), dpi=100, facecolor='#ECECEC')
self.canvas = Canvas(self.fig) self.canvas = Canvas(self.fig)
self.canvas.mpl_connect('pick_event', self.on_pick_event) self.canvas.mpl_connect('pick_event', self.on_pick_event)
...@@ -156,7 +156,7 @@ class GPSWidget(QtWidgets.QWidget): ...@@ -156,7 +156,7 @@ class GPSWidget(QtWidgets.QWidget):
self.repaint() self.repaint()
self.tracking_box.clear() self.tracking_box.clear()
def on_pick_event(self, event) -> None: def on_pick_event(self, event) -> Any:
""" """
On a GPS point being picked, display the data of that point on the On a GPS point being picked, display the data of that point on the
tracking box. tracking box.
...@@ -172,13 +172,13 @@ class GPSWidget(QtWidgets.QWidget): ...@@ -172,13 +172,13 @@ class GPSWidget(QtWidgets.QWidget):
# and longitude follows correspondingly. # and longitude follows correspondingly.
lat_dir = 'N' if picked_point.latitude > 0 else 'S' lat_dir = 'N' if picked_point.latitude > 0 else 'S'
long_dir = 'E' if picked_point.longitude > 0 else 'W' long_dir = 'E' if picked_point.longitude > 0 else 'W'
meta_separator = ' ' * 22 meta_separator = ' ' * 7
loc_separator = ' ' * 10 loc_separator = ' ' * 5
msg = ( msg = (
f'Mark: {picked_point.last_timemark}{meta_separator}' f' Mark: {picked_point.last_timemark}{meta_separator}'
f'Fix: {picked_point.fix_type}{meta_separator}' f'Fix: {picked_point.fix_type}{meta_separator}'
f'Sats: {picked_point.num_satellite_used}<br>' f'Sats: {picked_point.num_satellite_used}<br>'
f'Lat: {lat_dir}{abs(picked_point.latitude):.6f}{loc_separator}' f' Lat: {lat_dir}{abs(picked_point.latitude):.6f}{loc_separator}'
f'Long: {long_dir}{abs(picked_point.longitude):.6f}{loc_separator}' f'Long: {long_dir}{abs(picked_point.longitude):.6f}{loc_separator}'
f'Elev: {picked_point.height}{picked_point.height_unit}' f'Elev: {picked_point.height}{picked_point.height_unit}'
) )
...@@ -254,7 +254,7 @@ class GPSDialog(QtWidgets.QWidget): ...@@ -254,7 +254,7 @@ class GPSDialog(QtWidgets.QWidget):
bottom_layout = QtWidgets.QVBoxLayout() bottom_layout = QtWidgets.QVBoxLayout()
bottom_layout.addLayout(button_layout) bottom_layout.addLayout(button_layout)
self.info_text_browser.setFixedHeight(42) self.info_text_browser.setFixedHeight(45)
bottom_layout.addWidget(self.info_text_browser) bottom_layout.addWidget(self.info_text_browser)
main_layout.addLayout(bottom_layout) main_layout.addLayout(bottom_layout)
......
...@@ -40,7 +40,6 @@ class TimePowerSquaredDialog(QtWidgets.QWidget): ...@@ -40,7 +40,6 @@ class TimePowerSquaredDialog(QtWidgets.QWidget):
""" """
self.date_format: str = 'YYYY-MM-DD' self.date_format: str = 'YYYY-MM-DD'
self.setGeometry(50, 50, 1200, 800)
self.setWindowTitle("TPS Plot") self.setWindowTitle("TPS Plot")
main_layout = QtWidgets.QVBoxLayout() main_layout = QtWidgets.QVBoxLayout()
......
...@@ -231,7 +231,7 @@ class TimePowerSquaredWidget(plotting_widget.PlottingWidget): ...@@ -231,7 +231,7 @@ class TimePowerSquaredWidget(plotting_widget.PlottingWidget):
ax = self.create_axes(self.plotting_bot, plot_h) ax = self.create_axes(self.plotting_bot, plot_h)
ax.spines[['right', 'left', 'top', 'bottom']].set_visible(False) ax.spines[['right', 'left', 'top', 'bottom']].set_visible(False)
ax.text( ax.text(
-0.12, 1, -0.15, 1,
f"{get_seismic_chan_label(chan_id)} {c_data['samplerate']}sps", f"{get_seismic_chan_label(chan_id)} {c_data['samplerate']}sps",
horizontalalignment='left', horizontalalignment='left',
verticalalignment='top', verticalalignment='top',
......
...@@ -77,7 +77,6 @@ class WaveformDialog(QtWidgets.QWidget): ...@@ -77,7 +77,6 @@ class WaveformDialog(QtWidgets.QWidget):
date_format: format for date date_format: format for date
""" """
self.date_format: str = 'YYYY-MM-DD' self.date_format: str = 'YYYY-MM-DD'
self.setGeometry(50, 10, 1600, 700)
self.setWindowTitle("Raw Data Plot") self.setWindowTitle("Raw Data Plot")
main_layout = QtWidgets.QVBoxLayout() main_layout = QtWidgets.QVBoxLayout()
......
...@@ -7,6 +7,7 @@ from PySide2.QtWidgets import ( ...@@ -7,6 +7,7 @@ from PySide2.QtWidgets import (
QMainWindow, QWidget, QTextBrowser, QPushButton, QLineEdit, QDateEdit, QMainWindow, QWidget, QTextBrowser, QPushButton, QLineEdit, QDateEdit,
QListWidget, QCheckBox, QRadioButton, QMenu, QLabel, QFrame, QListWidget, QCheckBox, QRadioButton, QMenu, QLabel, QFrame,
QVBoxLayout, QHBoxLayout, QGridLayout, QAbstractItemView, QButtonGroup, QVBoxLayout, QHBoxLayout, QGridLayout, QAbstractItemView, QButtonGroup,
QSplitter,
) )
from PySide2.QtWidgets import ( from PySide2.QtWidgets import (
QAction, QActionGroup, QShortcut QAction, QActionGroup, QShortcut
...@@ -279,7 +280,6 @@ class UIMainWindow(object): ...@@ -279,7 +280,6 @@ class UIMainWindow(object):
:param main_window: QMainWindow - main GUI for user to interact with :param main_window: QMainWindow - main GUI for user to interact with
""" """
self.main_window = main_window self.main_window = main_window
main_window.resize(1798, 1110)
main_window.setWindowTitle("SOH Station Viewer") main_window.setWindowTitle("SOH Station Viewer")
self.central_widget = QWidget(main_window) self.central_widget = QWidget(main_window)
main_window.setCentralWidget(self.central_widget) main_window.setCentralWidget(self.central_widget)
...@@ -294,8 +294,6 @@ class UIMainWindow(object): ...@@ -294,8 +294,6 @@ class UIMainWindow(object):
self.set_first_row(main_layout) self.set_first_row(main_layout)
self.set_second_row(main_layout) self.set_second_row(main_layout)
self.tracking_info_text_browser.setFixedHeight(80)
main_layout.addWidget(self.tracking_info_text_browser)
self.create_menu_bar(main_window) self.create_menu_bar(main_window)
self.connect_signals(main_window) self.connect_signals(main_window)
self.create_shortcuts(main_window) self.create_shortcuts(main_window)
...@@ -352,7 +350,7 @@ class UIMainWindow(object): ...@@ -352,7 +350,7 @@ class UIMainWindow(object):
left_widget = QWidget(self.central_widget) left_widget = QWidget(self.central_widget)
h_layout.addWidget(left_widget) h_layout.addWidget(left_widget)
left_widget.setFixedWidth(240) left_widget.setFixedWidth(240)
left_widget.setMinimumHeight(650) # left_widget.setMinimumHeight(650)
left_layout = QVBoxLayout() left_layout = QVBoxLayout()
left_layout.setContentsMargins(0, 0, 0, 0) left_layout.setContentsMargins(0, 0, 0, 0)
left_layout.setSpacing(0) left_layout.setSpacing(0)
...@@ -360,12 +358,22 @@ class UIMainWindow(object): ...@@ -360,12 +358,22 @@ class UIMainWindow(object):
self.set_control_column(left_layout) self.set_control_column(left_layout)
plot_splitter = QSplitter(QtCore.Qt.Orientation.Vertical)
h_layout.addWidget(plot_splitter, 2)
self.plotting_widget = SOHWidget(self.main_window, self.plotting_widget = SOHWidget(self.main_window,
self.tracking_info_text_browser, self.tracking_info_text_browser,
'SOH', 'SOH',
self.main_window) self.main_window)
plot_splitter.addWidget(self.plotting_widget)
h_layout.addWidget(self.plotting_widget, 2) self.tracking_info_text_browser.setMinimumHeight(60)
self.tracking_info_text_browser.setMaximumHeight(80)
plot_splitter.addWidget(self.tracking_info_text_browser)
tracking_browser_idx = plot_splitter.indexOf(
self.tracking_info_text_browser
)
plot_splitter.setCollapsible(tracking_browser_idx, False)
def set_control_column(self, left_layout): def set_control_column(self, left_layout):
""" """
......