Forecast screen. Just a partial implementation: gui and info btn
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -6,6 +6,6 @@ to_do.txt
|
||||
csv_info.txt
|
||||
pyinstaller_cmd.txt
|
||||
themes/.current_theme
|
||||
*.bat
|
||||
launch.bat
|
||||
*.sh
|
||||
.vscode/
|
||||
|
||||
73
artemis.py
73
artemis.py
@@ -23,6 +23,7 @@ from PyQt5.QtCore import (QFileInfo,
|
||||
|
||||
from audio_player import AudioPlayer
|
||||
from space_weather_data import SpaceWeatherData
|
||||
from forecastdata import ForecastData
|
||||
from download_window import DownloadWindow
|
||||
from switchable_label import SwitchableLabelsIterable
|
||||
from constants import (Constants,
|
||||
@@ -31,8 +32,9 @@ from constants import (Constants,
|
||||
Database,
|
||||
ChecksumWhat,
|
||||
Messages,
|
||||
Signal,)
|
||||
from themes import Theme
|
||||
Signal,
|
||||
Months)
|
||||
from themesmanager import ThemeManager
|
||||
from utilities import (checksum_ok,
|
||||
uncheck_and_emit,
|
||||
pop_up,
|
||||
@@ -80,6 +82,7 @@ class Artemis(QMainWindow, Ui_MainWindow):
|
||||
self.current_signal_name = ''
|
||||
self.signal_names = []
|
||||
self.total_signals = 0
|
||||
|
||||
self.switchable_r_labels = SwitchableLabelsIterable(
|
||||
self.r0_now_lbl,
|
||||
self.r1_now_lbl,
|
||||
@@ -138,23 +141,23 @@ class Artemis(QMainWindow, Ui_MainWindow):
|
||||
self.a_quiet_lbl
|
||||
)
|
||||
|
||||
self.forecast_labels = (
|
||||
self.forecast_lbl_0,
|
||||
self.forecast_lbl_1,
|
||||
self.forecast_lbl_2,
|
||||
self.forecast_lbl_3,
|
||||
self.forecast_lbl_4,
|
||||
self.forecast_lbl_5,
|
||||
self.forecast_lbl_6,
|
||||
self.forecast_lbl_7,
|
||||
self.forecast_lbl_8
|
||||
self.space_weather_labels = (
|
||||
self.space_weather_lbl_0,
|
||||
self.space_weather_lbl_1,
|
||||
self.space_weather_lbl_2,
|
||||
self.space_weather_lbl_3,
|
||||
self.space_weather_lbl_4,
|
||||
self.space_weather_lbl_5,
|
||||
self.space_weather_lbl_6,
|
||||
self.space_weather_lbl_7,
|
||||
self.space_weather_lbl_8
|
||||
)
|
||||
|
||||
for lab in self.forecast_labels:
|
||||
for lab in self.space_weather_labels:
|
||||
lab.set_default_stylesheet()
|
||||
|
||||
self.forecast_label_container.labels = self.forecast_labels
|
||||
self.theme = Theme(self)
|
||||
self.space_weather_label_container.labels = self.space_weather_labels
|
||||
self.theme_manager = ThemeManager(self)
|
||||
|
||||
# Manage frequency filters.
|
||||
self.frequency_filters_btns = (
|
||||
@@ -501,18 +504,52 @@ class Artemis(QMainWindow, Ui_MainWindow):
|
||||
|
||||
# Space weather
|
||||
self.info_now_btn.clicked.connect(
|
||||
lambda : webbrowser.open(Constants.FORECAST_INFO)
|
||||
lambda: webbrowser.open(Constants.SPACE_WEATHER_INFO)
|
||||
)
|
||||
self.update_now_bar.clicked.connect(self.start_update_space_weather)
|
||||
self.update_now_bar.set_idle()
|
||||
self.space_weather_data = SpaceWeatherData()
|
||||
self.space_weather_data.update_complete.connect(self.update_space_weather)
|
||||
|
||||
# Forecast
|
||||
self.forecast_info_btn.clicked.connect(
|
||||
lambda: webbrowser.open(Constants.SPACE_WEATHER_INFO)
|
||||
)
|
||||
self.update_forecast_bar.clicked.connect(self.start_update_forecast)
|
||||
self.update_forecast_bar.set_idle()
|
||||
self.forecast_data = ForecastData()
|
||||
self.today_forecast_labels = []
|
||||
self.today_p1_forecast_labels = []
|
||||
self.today_p2_forecast_labels = []
|
||||
self.all_forecast_labels = []
|
||||
flags = ['', 'p1_', 'p2_']
|
||||
for flag in flags:
|
||||
title_lbl = getattr(self, "today_" + flag + "lbl")
|
||||
title_lbl.setText("-")
|
||||
for index in range(20):
|
||||
label = getattr(
|
||||
self,
|
||||
"forecast_today_" + flag + str(index) + "_lbl"
|
||||
)
|
||||
label.setText(Constants.UNKNOWN)
|
||||
self.all_forecast_labels.append(label)
|
||||
if flag == flags[0]:
|
||||
self.today_forecast_labels.append(label)
|
||||
if flag == flags[1]:
|
||||
self.today_p1_forecast_labels.append(label)
|
||||
if flag == flags[2]:
|
||||
self.today_p2_forecast_labels.append(label)
|
||||
|
||||
|
||||
# Final operations.
|
||||
self.theme.initialize()
|
||||
self.theme_manager.start()
|
||||
self.load_db()
|
||||
self.display_signals()
|
||||
|
||||
@pyqtSlot()
|
||||
def start_update_forecast(self):
|
||||
pass
|
||||
|
||||
@pyqtSlot()
|
||||
def start_update_space_weather(self):
|
||||
if not self.space_weather_data.is_updating:
|
||||
@@ -659,7 +696,7 @@ class Artemis(QMainWindow, Ui_MainWindow):
|
||||
val = int([x[4] for x in self.space_weather_data.sgas if "SSN" in x][0])
|
||||
self.sn_lbl.setText(f"{val:d}")
|
||||
|
||||
for label, pixmap in zip(self.forecast_labels, self.space_weather_data.images):
|
||||
for label, pixmap in zip(self.space_weather_labels, self.space_weather_data.images):
|
||||
label.pixmap = pixmap
|
||||
label.make_transparent()
|
||||
label.apply_pixmap()
|
||||
|
||||
1103
artemis.ui
1103
artemis.ui
File diff suppressed because it is too large
Load Diff
@@ -11,18 +11,20 @@ class ClickableProgressBar(QProgressBar):
|
||||
self.__text = ''
|
||||
super().__init__(parent)
|
||||
|
||||
def __set_text(self, text):
|
||||
self.__text = text
|
||||
# def __set_text(self, text):
|
||||
# self.__text = text
|
||||
|
||||
def text(self):
|
||||
return self.__text
|
||||
|
||||
def set_idle(self):
|
||||
self.__set_text(Constants.CLICK_TO_UPDATE_STR)
|
||||
# self.__set_text(Constants.CLICK_TO_UPDATE_STR)
|
||||
self.__text = Constants.CLICK_TO_UPDATE_STR
|
||||
self.setMaximum(self.minimum() + 1)
|
||||
|
||||
def set_updating(self):
|
||||
self.__set_text(Constants.UPDATING_STR)
|
||||
# self.__set_text(Constants.UPDATING_STR)
|
||||
self.__text = Constants.UPDATING_STR
|
||||
self.setMaximum(self.minimum())
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
|
||||
51
constants.py
51
constants.py
@@ -2,7 +2,7 @@ from collections import namedtuple
|
||||
from enum import Enum, auto
|
||||
|
||||
|
||||
class Ftype(object):
|
||||
class Ftype:
|
||||
FREQ = "freq"
|
||||
BAND = "band"
|
||||
|
||||
@@ -17,7 +17,7 @@ class ChecksumWhat(Enum):
|
||||
DB = auto()
|
||||
|
||||
|
||||
class Messages(object):
|
||||
class Messages:
|
||||
DB_UP_TO_DATE = "Already up to date"
|
||||
DB_UP_TO_DATE_MSG = "No newer version to download."
|
||||
DB_NEW_VER = "New version available"
|
||||
@@ -32,7 +32,7 @@ class Messages(object):
|
||||
BAD_DOWNLOAD_MSG = "Something went wrong with the downaload.\nCheck your internet connection and try again."
|
||||
|
||||
|
||||
class Signal(object):
|
||||
class Signal:
|
||||
NAME = "name"
|
||||
INF_FREQ = "inf_freq"
|
||||
SUP_FREQ = "sup_freq"
|
||||
@@ -48,7 +48,7 @@ class Signal(object):
|
||||
WIKI_CLICKED = "url_clicked"
|
||||
|
||||
|
||||
class Database(object):
|
||||
class Database:
|
||||
LINK_LOC = "https://aresvalley.com/Storage/Artemis/Database/data.zip"
|
||||
LINK_REF = "https://aresvalley.com/Storage/Artemis/Database/data.zip.log"
|
||||
NAME = "db.csv"
|
||||
@@ -73,7 +73,34 @@ class Database(object):
|
||||
Signal.CATEGORY_CODE,)
|
||||
|
||||
|
||||
class Constants(object):
|
||||
class ForecastColors:
|
||||
WARNING_COLOR = "#F95423"
|
||||
KP9_COLOR = "#FFCCCB"
|
||||
KP8_COLOR = "#FFCC9A"
|
||||
KP7_COLOR = "#FFFECD"
|
||||
KP6_COLOR = "#CDFFCC"
|
||||
KP5_COLOR = "#BEE3FE"
|
||||
|
||||
|
||||
class Months:
|
||||
MONTS = [
|
||||
"0",
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar",
|
||||
"Apr",
|
||||
"May",
|
||||
"Jun",
|
||||
"Jul",
|
||||
"Aug",
|
||||
"Sep",
|
||||
"Oct",
|
||||
"Nov",
|
||||
"Dec"
|
||||
]
|
||||
|
||||
|
||||
class Constants:
|
||||
CLICK_TO_UPDATE_STR = "Click to update"
|
||||
SIGIDWIKI = "https://www.sigidwiki.com/wiki/Signal_Identification_Guide"
|
||||
ADD_SIGNAL_LINK = "https://www.sigidwiki.com/index.php/Special:FormEdit/Signal/?preload=Signal_Identification_Wiki:Signal_form_preload_text"
|
||||
@@ -82,13 +109,13 @@ class Constants(object):
|
||||
RTL_SDL_LINK = "https://www.rtl-sdr.com/"
|
||||
UPDATING_STR = "Updating..."
|
||||
ACF_DOCS = "https://aresvalley.com/documentation/"
|
||||
FORECAST_XRAY = "https://services.swpc.noaa.gov/text/goes-xray-flux-primary.txt"
|
||||
FORECAST_PROT_EL = "https://services.swpc.noaa.gov/text/goes-particle-flux-primary.txt"
|
||||
FORECAST_AK_INDEX = "https://services.swpc.noaa.gov/text/wwv.txt"
|
||||
FORECAST_SGAS = "https://services.swpc.noaa.gov/text/sgas.txt"
|
||||
FORECAST_GEO_STORM = "https://services.swpc.noaa.gov/text/3-day-forecast.txt"
|
||||
FORECAST_INFO = "https://www.swpc.noaa.gov/sites/default/files/images/NOAAscales.pdf"
|
||||
FORECAST_IMGS = ["http://www.mmmonvhf.de/eme/eme.png",
|
||||
SPACE_WEATHER_XRAY = "https://services.swpc.noaa.gov/text/goes-xray-flux-primary.txt"
|
||||
SPACE_WEATHER_PROT_EL = "https://services.swpc.noaa.gov/text/goes-particle-flux-primary.txt"
|
||||
SPACE_WEATHER_AK_INDEX = "https://services.swpc.noaa.gov/text/wwv.txt"
|
||||
SPACE_WEATHER_SGAS = "https://services.swpc.noaa.gov/text/sgas.txt"
|
||||
SPACE_WEATHER_GEO_STORM = "https://services.swpc.noaa.gov/text/3-day-forecast.txt"
|
||||
SPACE_WEATHER_INFO = "https://www.swpc.noaa.gov/sites/default/files/images/NOAAscales.pdf"
|
||||
SPACE_WEATHER_IMGS = ["http://www.mmmonvhf.de/eme/eme.png",
|
||||
"http://www.mmmonvhf.de/ms/ms.png",
|
||||
"http://www.mmmonvhf.de/es/es.png",
|
||||
"http://www.mmmonvhf.de/solar/solar.png",
|
||||
|
||||
@@ -8,14 +8,16 @@ class FixedAspectRatioLabel(QLabel):
|
||||
self.pixmap = None
|
||||
|
||||
def set_default_stylesheet(self):
|
||||
self.setStyleSheet("""
|
||||
color: #ffffff;
|
||||
background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0,stop:0 #304352 ,stop: 1 #d7d2cc);
|
||||
""")
|
||||
self.setStyleSheet("border: 3px;")
|
||||
# self.setStyleSheet("""
|
||||
# color: #ffffff;
|
||||
# background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0,stop:0 #304352 ,stop: 1 #d7d2cc);
|
||||
# """)
|
||||
|
||||
def make_transparent(self):
|
||||
self.setText('')
|
||||
self.setStyleSheet("background-color: transparent;")
|
||||
self.setStyleSheet("border: 0px;")
|
||||
# self.setStyleSheet("background-color: transparent;")
|
||||
|
||||
def apply_pixmap(self):
|
||||
if self.pixmap:
|
||||
|
||||
3
forecastdata.py
Normal file
3
forecastdata.py
Normal file
@@ -0,0 +1,3 @@
|
||||
class ForecastData:
|
||||
def __init__(self):
|
||||
pass
|
||||
@@ -1,6 +1,6 @@
|
||||
from PyQt5.QtGui import QPixmap
|
||||
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject
|
||||
from threads import UpadteSpaceWeatherThread, ThreadStatus
|
||||
from threads import UpdateSpaceWeatherThread, ThreadStatus
|
||||
|
||||
|
||||
class SpaceWeatherData(QObject):
|
||||
@@ -24,7 +24,7 @@ class SpaceWeatherData(QObject):
|
||||
QPixmap(),
|
||||
QPixmap()
|
||||
]
|
||||
self.__update_thread = UpadteSpaceWeatherThread(self)
|
||||
self.__update_thread = UpdateSpaceWeatherThread(self)
|
||||
self.__update_thread.finished.connect(self.__parse_and_emit_signal)
|
||||
|
||||
@property
|
||||
|
||||
@@ -1,20 +1,32 @@
|
||||
from PyQt5.QtWidgets import QLabel
|
||||
from constants import ForecastColors
|
||||
|
||||
|
||||
class SwitchableLabel(QLabel):
|
||||
class _BaseSwitchableLabel(QLabel):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.is_on = False
|
||||
|
||||
def switch_on(self):
|
||||
self.is_on = True
|
||||
|
||||
def switch_off(self):
|
||||
self.is_on = False
|
||||
|
||||
|
||||
class SwitchableLabel(_BaseSwitchableLabel):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.switch_on_colors = ()
|
||||
self.switch_off_colors = ()
|
||||
self.text_color = ''
|
||||
self.is_on = False
|
||||
|
||||
def switch_on(self):
|
||||
self.is_on = True
|
||||
super().switch_on()
|
||||
self.__apply_colors(*self.switch_on_colors)
|
||||
|
||||
def switch_off(self):
|
||||
self.is_on = False
|
||||
super().switch_off()
|
||||
self.__apply_colors(*self.switch_off_colors)
|
||||
|
||||
def __apply_colors(self, start, end):
|
||||
@@ -26,7 +38,47 @@ class SwitchableLabel(QLabel):
|
||||
)
|
||||
|
||||
|
||||
class SwitchableLabelsIterable(object):
|
||||
class SingleColorSwitchableLabel(_BaseSwitchableLabel):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.active_color = ForecastColors.WARNING_COLOR
|
||||
|
||||
def switch_on(self):
|
||||
super().switch_on()
|
||||
self.setStyleSheet(f"background-color: {self.active_color};")
|
||||
|
||||
def switch_off(self):
|
||||
super().switch_off()
|
||||
self.setStyleSheet("background-color: transparent;")
|
||||
|
||||
|
||||
class MultiColorSwitchableLabel(_BaseSwitchableLabel):
|
||||
|
||||
LEVEL_COLORS = {
|
||||
9: ForecastColors.KP9_COLOR,
|
||||
8: ForecastColors.KP8_COLOR,
|
||||
7: ForecastColors.KP7_COLOR,
|
||||
6: ForecastColors.KP6_COLOR,
|
||||
5: ForecastColors.KP5_COLOR
|
||||
}
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.level = 0
|
||||
|
||||
def switch_on(self):
|
||||
if 5 <= self.level <= 9:
|
||||
super().switch_on()
|
||||
self.setStyleSheet(f"""
|
||||
background-color: {self.LEVEL_COLORS[self.level]};
|
||||
""")
|
||||
|
||||
def switch_off(self):
|
||||
super().switch_off()
|
||||
self.setStyleSheet("background-color: transparent;")
|
||||
|
||||
|
||||
class SwitchableLabelsIterable:
|
||||
def __init__(self, *labels):
|
||||
self.labels = labels
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ from switchable_label import SwitchableLabelsIterable
|
||||
from utilities import pop_up
|
||||
|
||||
|
||||
class ThemeConstants(object):
|
||||
class ThemeConstants:
|
||||
FOLDER = "themes"
|
||||
EXTENSION = ".qss"
|
||||
ICONS_FOLDER = "icons"
|
||||
@@ -26,7 +26,7 @@ class ThemeConstants(object):
|
||||
THEME_NOT_FOUND = "Theme not found"
|
||||
MISSING_THEME = "Missing theme in '" + FOLDER + "' folder."
|
||||
|
||||
class Theme(object):
|
||||
class ThemeManager:
|
||||
def __init__(self, parent):
|
||||
self.__parent = parent
|
||||
self.__parent.active_color = ThemeConstants.DEFAULT_ACTIVE_COLOR
|
||||
@@ -41,7 +41,7 @@ class Theme(object):
|
||||
ThemeConstants.ICONS_FOLDER
|
||||
)
|
||||
|
||||
self.__forecast_labels = SwitchableLabelsIterable(
|
||||
self.__space_weather_labels = SwitchableLabelsIterable(
|
||||
*list(
|
||||
chain(
|
||||
self.__parent.switchable_r_labels,
|
||||
@@ -55,11 +55,11 @@ class Theme(object):
|
||||
)
|
||||
)
|
||||
|
||||
self.__forecast_labels.set(
|
||||
self.__space_weather_labels.set(
|
||||
"switch_on_colors",
|
||||
ThemeConstants.DEFAULT_ON_COLORS
|
||||
)
|
||||
self.__forecast_labels.set(
|
||||
self.__space_weather_labels.set(
|
||||
"switch_off_colors", ThemeConstants.DEFAULT_OFF_COLORS
|
||||
)
|
||||
|
||||
@@ -106,7 +106,7 @@ class Theme(object):
|
||||
self.__parent.active_color,
|
||||
self.__parent.inactive_color
|
||||
)
|
||||
self.__forecast_labels.refresh()
|
||||
self.__space_weather_labels.refresh()
|
||||
|
||||
def __pretty_name(self, bad_name):
|
||||
return ' '.join(
|
||||
@@ -257,20 +257,20 @@ class Theme(object):
|
||||
inactive_color_ok = True
|
||||
if quality.lower() == Constants.TEXT_COLOR:
|
||||
text_color_ok = True
|
||||
self.__forecast_labels.set(
|
||||
self.__space_weather_labels.set(
|
||||
"text_color",
|
||||
color
|
||||
)
|
||||
if color_len == 2:
|
||||
if quality.lower() == Constants.LABEL_ON_COLOR:
|
||||
switch_on_color_ok = True
|
||||
self.__forecast_labels.set(
|
||||
self.__space_weather_labels.set(
|
||||
"switch_on_colors",
|
||||
color
|
||||
)
|
||||
if quality.lower() == Constants.LABEL_OFF_COLOR:
|
||||
switch_off_color_ok = True
|
||||
self.__forecast_labels.set(
|
||||
self.__space_weather_labels.set(
|
||||
"switch_off_colors",
|
||||
color
|
||||
)
|
||||
@@ -280,17 +280,17 @@ class Theme(object):
|
||||
self.__parent.inactive_color = ThemeConstants.DEFAULT_INACTIVE_COLOR
|
||||
|
||||
if not (switch_on_color_ok and switch_off_color_ok):
|
||||
self.__forecast_labels.set(
|
||||
self.__space_weather_labels.set(
|
||||
"switch_on_colors",
|
||||
ThemeConstants.DEFAULT_ON_COLORS
|
||||
)
|
||||
self.__forecast_labels.set(
|
||||
self.__space_weather_labels.set(
|
||||
"switch_off_colors",
|
||||
ThemeConstants.DEFAULT_OFF_COLORS
|
||||
)
|
||||
|
||||
if not text_color_ok:
|
||||
self.__forecast_labels.set(
|
||||
self.__space_weather_labels.set(
|
||||
"text_color",
|
||||
ThemeConstants.DEFAULT_TEXT_COLOR
|
||||
)
|
||||
@@ -305,7 +305,7 @@ class Theme(object):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def initialize(self):
|
||||
def start(self):
|
||||
current_theme_file = os.path.join(
|
||||
ThemeConstants.FOLDER,
|
||||
ThemeConstants.CURRENT
|
||||
@@ -66,7 +66,7 @@ class DownloadThread(_BaseDownloadThread):
|
||||
self.status = ThreadStatus.OK
|
||||
|
||||
|
||||
class UpadteSpaceWeatherThread(_BaseDownloadThread):
|
||||
class UpdateSpaceWeatherThread(_BaseDownloadThread):
|
||||
|
||||
__properties = ("xray", "prot_el", "ak_index", "sgas", "geo_storm")
|
||||
|
||||
@@ -79,12 +79,12 @@ class UpadteSpaceWeatherThread(_BaseDownloadThread):
|
||||
return await resp.read()
|
||||
|
||||
async def __download_property(self, session, property_name):
|
||||
link = getattr(Constants, "FORECAST_" + property_name.upper())
|
||||
link = getattr(Constants, "SPACE_WEATHER_" + property_name.upper())
|
||||
data = await self.__download_resource(session, link)
|
||||
setattr(self.__space_weather_data, property_name, str(data, 'utf-8'))
|
||||
|
||||
async def __download_image(self, session, n):
|
||||
im = await self.__download_resource(session, Constants.FORECAST_IMGS[n])
|
||||
im = await self.__download_resource(session, Constants.SPACE_WEATHER_IMGS[n])
|
||||
self.__space_weather_data.images[n].loadFromData(im)
|
||||
|
||||
async def __download_resources(self, *links):
|
||||
@@ -96,7 +96,7 @@ class UpadteSpaceWeatherThread(_BaseDownloadThread):
|
||||
asyncio.create_task(self.__download_property(session, p))
|
||||
)
|
||||
|
||||
tot_images = range(len(Constants.FORECAST_IMGS))
|
||||
tot_images = range(len(Constants.SPACE_WEATHER_IMGS))
|
||||
t1 = []
|
||||
for im_number in tot_images:
|
||||
t1.append(
|
||||
|
||||
Reference in New Issue
Block a user