Switch from filter panel to signal panel with double-click on

signal name. Also make minor style changes
This commit is contained in:
alessandro90
2019-06-02 14:10:06 +02:00
parent 10724e548a
commit 8cb81dd225
11 changed files with 87 additions and 56 deletions

View File

@@ -1,2 +1,2 @@
[flake8]
ignore = E221, E501
ignore = E221, E501, W605, W504

View File

@@ -485,9 +485,8 @@ class Artemis(QMainWindow, Ui_MainWindow):
# Left list widget and search bar.
self.search_bar.textChanged.connect(self.display_signals)
self.signals_list.currentItemChanged.connect(self.display_specs)
self.signals_list.itemDoubleClicked.connect(
lambda: self.main_tab.setCurrentWidget(self.signal_properties_tab)
)
self.signals_list.itemDoubleClicked.connect(self.set_visible_tab)
self.audio_widget = AudioPlayer(
self.play,
self.pause,
@@ -537,6 +536,13 @@ class Artemis(QMainWindow, Ui_MainWindow):
self.load_db()
self.display_signals()
@pyqtSlot()
def set_visible_tab(self):
if self.main_tab.currentWidget() != self.signal_properties_tab:
self.main_tab.setCurrentWidget(self.signal_properties_tab)
else:
self.main_tab.setCurrentWidget(self.filter_tab)
@pyqtSlot()
def start_update_forecast(self):
"""Start the update of the 3-day forecast screen.
@@ -582,7 +588,10 @@ class Artemis(QMainWindow, Ui_MainWindow):
self.update_now_bar.set_idle()
if status_ok:
xray_long = safe_cast(self.space_weather_data.xray[-1][7], float)
def format_text(letter, power): return letter + f"{xray_long * 10**power:.1f}"
def format_text(letter, power):
return letter + f"{xray_long * 10**power:.1f}"
if xray_long < 1e-8 and xray_long != -1.00e+05:
self.peak_flux_lbl.setText(format_text("<A", 8))
elif xray_long >= 1e-8 and xray_long < 1e-7:

View File

@@ -14,7 +14,7 @@ class AudioPlayer(QObject):
method, set_audio_player, which loads the current file and refresh_btns_colors.
Everything else is managed internally."""
_time_step = 500 # Milliseconds.
_TIME_STEP = 500 # Milliseconds.
def __init__(self, play,
pause,
@@ -111,10 +111,10 @@ class AudioPlayer(QObject):
if not self._paused:
if self._first_call:
self._first_call = False
mixer.init(frequency=AudioSegment.from_ogg(
self._audio_file
).frame_rate,
buffer=2048)
mixer.init(
frequency=AudioSegment.from_ogg(self._audio_file).frame_rate,
buffer=2048
)
mixer.music.load(self._audio_file)
self._set_volume()
self._set_max_progress_bar()
@@ -122,7 +122,7 @@ class AudioPlayer(QObject):
else:
mixer.music.unpause()
self._paused = False
self._timer.start(self._time_step)
self._timer.start(self._TIME_STEP)
self._enable_buttons(False, True, True)
@pyqtSlot()

View File

@@ -1,6 +1,7 @@
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtCore import pyqtSlot
class DoubleTextButton(QPushButton):
"""Subclass QPushButton.

View File

@@ -14,8 +14,7 @@ class FixedAspectRatioLabel(QLabel):
"""Set the initial stylesheet of the label."""
self.setStyleSheet("""border-width: 1px;
border-style: solid;
border-color: black;"""
)
border-color: black;""")
def make_transparent(self):
"""Make the label transparent.

View File

@@ -5,7 +5,8 @@ from PyQt5.QtCore import QSize
class FixedAspectRatioWidget(QWidget):
"""Subclass QWidget. Keep all the internal labels to a fixed aspect ratio."""
space = 10
SPACE = 10
def __init__(self, parent=None):
"""Initialize the instance."""
super().__init__(parent)
@@ -14,7 +15,7 @@ class FixedAspectRatioWidget(QWidget):
def resizeEvent(self, event):
"""Override QWidget.resizeEvent. Rescale all the internal widgets."""
h, w = self.height(), self.width()
h_lbl = h / 9 - self.space
h_lbl = h / 9 - self.SPACE
w_lbl = 5 * h_lbl
w_pad = w - 10
if w_lbl > w_pad:

View File

@@ -71,7 +71,9 @@ class _ColorsHandler:
def _color_is_valid(self):
"""Return if the color (or the list of colors) has a valid html format."""
pattern = "#([a-zA-Z0-9]){6}"
def match_ok(col): return bool(re.match(pattern, col)) and len(col) == 7
def match_ok(col):
return bool(re.match(pattern, col)) and len(col) == 7
if not self.is_simple_string:
if len(self.color_list) <= self.MAX_COLORS:
@@ -81,7 +83,6 @@ class _ColorsHandler:
else:
return match_ok(self.color_str)
def __init__(self, simple_color_list, double_color_list):
"""Initialize the lists of valid _Color objects."""
self.simple_color_list = simple_color_list
@@ -197,7 +198,8 @@ class ThemeManager:
def _pretty_name(self, bad_name):
"""Return a well-formatted theme name."""
return ' '.join(
map(lambda s: s.capitalize(),
map(
lambda s: s.capitalize(),
bad_name.split('_')
)
)

View File

@@ -126,7 +126,7 @@ class _AsyncDownloader:
class UpdateSpaceWeatherThread(BaseDownloadThread, _AsyncDownloader):
"""Subclass BaseDownloadThread. Downlaod the space weather data."""
_properties = ("xray", "prot_el", "ak_index", "sgas", "geo_storm")
_PROPERTIES = ("xray", "prot_el", "ak_index", "sgas", "geo_storm")
def __init__(self, space_weather_data):
"""Initialize the a local space_weather_data."""
@@ -151,7 +151,7 @@ class UpdateSpaceWeatherThread(BaseDownloadThread, _AsyncDownloader):
session = aiohttp.ClientSession()
try:
t = []
for p in self._properties:
for p in self._PROPERTIES:
t.append(
asyncio.create_task(self._download_property(session, p))
)

View File

@@ -8,6 +8,7 @@ from PyQt5.QtWidgets import QMessageBox
from constants import Constants, Signal, Database, ChecksumWhat
def resource_path(relative_path):
"""Get absolute path to resource, works for dev and for PyInstaller."""
try:
@@ -16,12 +17,14 @@ def resource_path(relative_path):
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
def uncheck_and_emit(button):
"""Set the button to the unchecked state and emit the clicked signal."""
if button.isChecked():
button.setChecked(False)
button.clicked.emit()
def pop_up(cls, title, text,
informative_text=None,
connection=None,
@@ -47,6 +50,7 @@ def pop_up(cls, title, text,
msg.adjustSize()
return msg
def checksum_ok(data, what):
"""Check whether the checksum of the 'data' argument is correct."""
code = hashlib.sha256()
@@ -66,6 +70,7 @@ def checksum_ok(data, what):
raise
return code.hexdigest() == reference
def connect_events_to_func(events_to_connect, fun_to_connect, fun_args):
"""Connect all elements of events_to_connect to the callable fun_to_connect.
@@ -77,23 +82,27 @@ def connect_events_to_func(events_to_connect, fun_to_connect, fun_args):
for event in events_to_connect:
event.connect(fun_to_connect)
def filters_limit(spinbox, filter_unit, confidence, sign=1):
"""Return the actual limit of a numerical filter."""
band_filter = spinbox.value() * Constants.CONVERSION_FACTORS[filter_unit.currentText()]
return band_filter + sign * (confidence.value() * band_filter) // 100
def is_undef_freq(current_signal):
"""Return whether the lower or upper frequency of a signal is undefined."""
lower_freq = current_signal.at[Signal.INF_FREQ]
upper_freq = current_signal.at[Signal.SUP_FREQ]
return lower_freq == Constants.UNKNOWN or upper_freq == Constants.UNKNOWN
def is_undef_band(current_signal):
"""Return whether the lower or upper band of a signal is undefined."""
lower_band = current_signal.at[Signal.INF_BAND]
upper_band = current_signal.at[Signal.SUP_BAND]
return lower_band == Constants.UNKNOWN or upper_band == Constants.UNKNOWN
def _change_unit(str_num):
"""Return a scale factor given the number of digits of a numeric string."""
digits = len(str_num)
@@ -106,6 +115,7 @@ def _change_unit(str_num):
else:
return 10**9
def format_numbers(lower, upper):
"""Return the string which displays the numeric limits of a filter."""
units = {1: 'Hz', 1000: 'kHz', 10**6: 'MHz', 10**9: 'GHz'}
@@ -128,6 +138,7 @@ def format_numbers(lower, upper):
else:
return f"{lower:,} {units[lower_factor]}"
def safe_cast(value, cast_type, default=-1):
"""Call 'cast_type(value)' and return the result.

View File

@@ -115,9 +115,15 @@ class SpaceWeatherData(_BaseWeatherData):
def _make_labels_table(forecast, probabilities, rows):
"""Organize all the arguments to feed _get_lbl_value."""
def get_first_split(x): return x.split("/")[0]
def get_second_split(x): return x.split("/")[1]
def get_third_split(x): return x.split("/")[2]
def get_first_split(x):
return x.split("/")[0]
def get_second_split(x):
return x.split("/")[1]
def get_third_split(x):
return x.split("/")[2]
solar_row = rows["solar_row"]
event_row = rows["event_row"]
rb_now_row = rows["rb_now_row"]
@@ -192,6 +198,7 @@ def _make_labels_table(forecast, probabilities, rows):
]
]
def _get_lbl_value(data, row, col, f=None):
"""Return the well-formatted string-value of the label."""
val = data[row][col]
@@ -202,6 +209,7 @@ def _get_lbl_value(data, row, col, f=None):
val = val.lstrip('0')
return val
class ForecastData(_BaseWeatherData):
"""3-day forecast class. Extends _BaseWeatherData."""