Forecast screen. Just a partial implementation: gui and info btn

This commit is contained in:
alessandro90
2019-05-04 17:55:17 +02:00
parent dbfe2cd0d5
commit 175cb66c76
11 changed files with 1394 additions and 194 deletions

2
.gitignore vendored
View File

@@ -6,6 +6,6 @@ to_do.txt
csv_info.txt csv_info.txt
pyinstaller_cmd.txt pyinstaller_cmd.txt
themes/.current_theme themes/.current_theme
*.bat launch.bat
*.sh *.sh
.vscode/ .vscode/

View File

@@ -23,6 +23,7 @@ from PyQt5.QtCore import (QFileInfo,
from audio_player import AudioPlayer from audio_player import AudioPlayer
from space_weather_data import SpaceWeatherData from space_weather_data import SpaceWeatherData
from forecastdata import ForecastData
from download_window import DownloadWindow from download_window import DownloadWindow
from switchable_label import SwitchableLabelsIterable from switchable_label import SwitchableLabelsIterable
from constants import (Constants, from constants import (Constants,
@@ -31,8 +32,9 @@ from constants import (Constants,
Database, Database,
ChecksumWhat, ChecksumWhat,
Messages, Messages,
Signal,) Signal,
from themes import Theme Months)
from themesmanager import ThemeManager
from utilities import (checksum_ok, from utilities import (checksum_ok,
uncheck_and_emit, uncheck_and_emit,
pop_up, pop_up,
@@ -80,6 +82,7 @@ class Artemis(QMainWindow, Ui_MainWindow):
self.current_signal_name = '' self.current_signal_name = ''
self.signal_names = [] self.signal_names = []
self.total_signals = 0 self.total_signals = 0
self.switchable_r_labels = SwitchableLabelsIterable( self.switchable_r_labels = SwitchableLabelsIterable(
self.r0_now_lbl, self.r0_now_lbl,
self.r1_now_lbl, self.r1_now_lbl,
@@ -138,23 +141,23 @@ class Artemis(QMainWindow, Ui_MainWindow):
self.a_quiet_lbl self.a_quiet_lbl
) )
self.forecast_labels = ( self.space_weather_labels = (
self.forecast_lbl_0, self.space_weather_lbl_0,
self.forecast_lbl_1, self.space_weather_lbl_1,
self.forecast_lbl_2, self.space_weather_lbl_2,
self.forecast_lbl_3, self.space_weather_lbl_3,
self.forecast_lbl_4, self.space_weather_lbl_4,
self.forecast_lbl_5, self.space_weather_lbl_5,
self.forecast_lbl_6, self.space_weather_lbl_6,
self.forecast_lbl_7, self.space_weather_lbl_7,
self.forecast_lbl_8 self.space_weather_lbl_8
) )
for lab in self.forecast_labels: for lab in self.space_weather_labels:
lab.set_default_stylesheet() lab.set_default_stylesheet()
self.forecast_label_container.labels = self.forecast_labels self.space_weather_label_container.labels = self.space_weather_labels
self.theme = Theme(self) self.theme_manager = ThemeManager(self)
# Manage frequency filters. # Manage frequency filters.
self.frequency_filters_btns = ( self.frequency_filters_btns = (
@@ -501,18 +504,52 @@ class Artemis(QMainWindow, Ui_MainWindow):
# Space weather # Space weather
self.info_now_btn.clicked.connect( 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.clicked.connect(self.start_update_space_weather)
self.update_now_bar.set_idle() self.update_now_bar.set_idle()
self.space_weather_data = SpaceWeatherData() self.space_weather_data = SpaceWeatherData()
self.space_weather_data.update_complete.connect(self.update_space_weather) 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. # Final operations.
self.theme.initialize() self.theme_manager.start()
self.load_db() self.load_db()
self.display_signals() self.display_signals()
@pyqtSlot()
def start_update_forecast(self):
pass
@pyqtSlot() @pyqtSlot()
def start_update_space_weather(self): def start_update_space_weather(self):
if not self.space_weather_data.is_updating: 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]) val = int([x[4] for x in self.space_weather_data.sgas if "SSN" in x][0])
self.sn_lbl.setText(f"{val:d}") 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.pixmap = pixmap
label.make_transparent() label.make_transparent()
label.apply_pixmap() label.apply_pixmap()

1103
artemis.ui

File diff suppressed because it is too large Load Diff

View File

@@ -11,18 +11,20 @@ class ClickableProgressBar(QProgressBar):
self.__text = '' self.__text = ''
super().__init__(parent) super().__init__(parent)
def __set_text(self, text): # def __set_text(self, text):
self.__text = text # self.__text = text
def text(self): def text(self):
return self.__text return self.__text
def set_idle(self): 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) self.setMaximum(self.minimum() + 1)
def set_updating(self): 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()) self.setMaximum(self.minimum())
def mousePressEvent(self, event): def mousePressEvent(self, event):

View File

@@ -2,7 +2,7 @@ from collections import namedtuple
from enum import Enum, auto from enum import Enum, auto
class Ftype(object): class Ftype:
FREQ = "freq" FREQ = "freq"
BAND = "band" BAND = "band"
@@ -17,7 +17,7 @@ class ChecksumWhat(Enum):
DB = auto() DB = auto()
class Messages(object): class Messages:
DB_UP_TO_DATE = "Already up to date" DB_UP_TO_DATE = "Already up to date"
DB_UP_TO_DATE_MSG = "No newer version to download." DB_UP_TO_DATE_MSG = "No newer version to download."
DB_NEW_VER = "New version available" 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." BAD_DOWNLOAD_MSG = "Something went wrong with the downaload.\nCheck your internet connection and try again."
class Signal(object): class Signal:
NAME = "name" NAME = "name"
INF_FREQ = "inf_freq" INF_FREQ = "inf_freq"
SUP_FREQ = "sup_freq" SUP_FREQ = "sup_freq"
@@ -48,7 +48,7 @@ class Signal(object):
WIKI_CLICKED = "url_clicked" WIKI_CLICKED = "url_clicked"
class Database(object): class Database:
LINK_LOC = "https://aresvalley.com/Storage/Artemis/Database/data.zip" LINK_LOC = "https://aresvalley.com/Storage/Artemis/Database/data.zip"
LINK_REF = "https://aresvalley.com/Storage/Artemis/Database/data.zip.log" LINK_REF = "https://aresvalley.com/Storage/Artemis/Database/data.zip.log"
NAME = "db.csv" NAME = "db.csv"
@@ -73,7 +73,34 @@ class Database(object):
Signal.CATEGORY_CODE,) 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" CLICK_TO_UPDATE_STR = "Click to update"
SIGIDWIKI = "https://www.sigidwiki.com/wiki/Signal_Identification_Guide" 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" 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/" RTL_SDL_LINK = "https://www.rtl-sdr.com/"
UPDATING_STR = "Updating..." UPDATING_STR = "Updating..."
ACF_DOCS = "https://aresvalley.com/documentation/" ACF_DOCS = "https://aresvalley.com/documentation/"
FORECAST_XRAY = "https://services.swpc.noaa.gov/text/goes-xray-flux-primary.txt" SPACE_WEATHER_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" SPACE_WEATHER_PROT_EL = "https://services.swpc.noaa.gov/text/goes-particle-flux-primary.txt"
FORECAST_AK_INDEX = "https://services.swpc.noaa.gov/text/wwv.txt" SPACE_WEATHER_AK_INDEX = "https://services.swpc.noaa.gov/text/wwv.txt"
FORECAST_SGAS = "https://services.swpc.noaa.gov/text/sgas.txt" SPACE_WEATHER_SGAS = "https://services.swpc.noaa.gov/text/sgas.txt"
FORECAST_GEO_STORM = "https://services.swpc.noaa.gov/text/3-day-forecast.txt" SPACE_WEATHER_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" SPACE_WEATHER_INFO = "https://www.swpc.noaa.gov/sites/default/files/images/NOAAscales.pdf"
FORECAST_IMGS = ["http://www.mmmonvhf.de/eme/eme.png", SPACE_WEATHER_IMGS = ["http://www.mmmonvhf.de/eme/eme.png",
"http://www.mmmonvhf.de/ms/ms.png", "http://www.mmmonvhf.de/ms/ms.png",
"http://www.mmmonvhf.de/es/es.png", "http://www.mmmonvhf.de/es/es.png",
"http://www.mmmonvhf.de/solar/solar.png", "http://www.mmmonvhf.de/solar/solar.png",

View File

@@ -8,14 +8,16 @@ class FixedAspectRatioLabel(QLabel):
self.pixmap = None self.pixmap = None
def set_default_stylesheet(self): def set_default_stylesheet(self):
self.setStyleSheet(""" self.setStyleSheet("border: 3px;")
color: #ffffff; # self.setStyleSheet("""
background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0,stop:0 #304352 ,stop: 1 #d7d2cc); # color: #ffffff;
""") # background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0,stop:0 #304352 ,stop: 1 #d7d2cc);
# """)
def make_transparent(self): def make_transparent(self):
self.setText('') self.setText('')
self.setStyleSheet("background-color: transparent;") self.setStyleSheet("border: 0px;")
# self.setStyleSheet("background-color: transparent;")
def apply_pixmap(self): def apply_pixmap(self):
if self.pixmap: if self.pixmap:

3
forecastdata.py Normal file
View File

@@ -0,0 +1,3 @@
class ForecastData:
def __init__(self):
pass

View File

@@ -1,6 +1,6 @@
from PyQt5.QtGui import QPixmap from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject
from threads import UpadteSpaceWeatherThread, ThreadStatus from threads import UpdateSpaceWeatherThread, ThreadStatus
class SpaceWeatherData(QObject): class SpaceWeatherData(QObject):
@@ -24,7 +24,7 @@ class SpaceWeatherData(QObject):
QPixmap(), QPixmap(),
QPixmap() QPixmap()
] ]
self.__update_thread = UpadteSpaceWeatherThread(self) self.__update_thread = UpdateSpaceWeatherThread(self)
self.__update_thread.finished.connect(self.__parse_and_emit_signal) self.__update_thread.finished.connect(self.__parse_and_emit_signal)
@property @property

View File

@@ -1,20 +1,32 @@
from PyQt5.QtWidgets import QLabel 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): def __init__(self, parent=None):
super().__init__(parent) super().__init__(parent)
self.switch_on_colors = () self.switch_on_colors = ()
self.switch_off_colors = () self.switch_off_colors = ()
self.text_color = '' self.text_color = ''
self.is_on = False
def switch_on(self): def switch_on(self):
self.is_on = True super().switch_on()
self.__apply_colors(*self.switch_on_colors) self.__apply_colors(*self.switch_on_colors)
def switch_off(self): def switch_off(self):
self.is_on = False super().switch_off()
self.__apply_colors(*self.switch_off_colors) self.__apply_colors(*self.switch_off_colors)
def __apply_colors(self, start, end): 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): def __init__(self, *labels):
self.labels = labels self.labels = labels

View File

@@ -10,7 +10,7 @@ from switchable_label import SwitchableLabelsIterable
from utilities import pop_up from utilities import pop_up
class ThemeConstants(object): class ThemeConstants:
FOLDER = "themes" FOLDER = "themes"
EXTENSION = ".qss" EXTENSION = ".qss"
ICONS_FOLDER = "icons" ICONS_FOLDER = "icons"
@@ -26,7 +26,7 @@ class ThemeConstants(object):
THEME_NOT_FOUND = "Theme not found" THEME_NOT_FOUND = "Theme not found"
MISSING_THEME = "Missing theme in '" + FOLDER + "' folder." MISSING_THEME = "Missing theme in '" + FOLDER + "' folder."
class Theme(object): class ThemeManager:
def __init__(self, parent): def __init__(self, parent):
self.__parent = parent self.__parent = parent
self.__parent.active_color = ThemeConstants.DEFAULT_ACTIVE_COLOR self.__parent.active_color = ThemeConstants.DEFAULT_ACTIVE_COLOR
@@ -41,7 +41,7 @@ class Theme(object):
ThemeConstants.ICONS_FOLDER ThemeConstants.ICONS_FOLDER
) )
self.__forecast_labels = SwitchableLabelsIterable( self.__space_weather_labels = SwitchableLabelsIterable(
*list( *list(
chain( chain(
self.__parent.switchable_r_labels, self.__parent.switchable_r_labels,
@@ -55,11 +55,11 @@ class Theme(object):
) )
) )
self.__forecast_labels.set( self.__space_weather_labels.set(
"switch_on_colors", "switch_on_colors",
ThemeConstants.DEFAULT_ON_COLORS ThemeConstants.DEFAULT_ON_COLORS
) )
self.__forecast_labels.set( self.__space_weather_labels.set(
"switch_off_colors", ThemeConstants.DEFAULT_OFF_COLORS "switch_off_colors", ThemeConstants.DEFAULT_OFF_COLORS
) )
@@ -106,7 +106,7 @@ class Theme(object):
self.__parent.active_color, self.__parent.active_color,
self.__parent.inactive_color self.__parent.inactive_color
) )
self.__forecast_labels.refresh() self.__space_weather_labels.refresh()
def __pretty_name(self, bad_name): def __pretty_name(self, bad_name):
return ' '.join( return ' '.join(
@@ -257,20 +257,20 @@ class Theme(object):
inactive_color_ok = True inactive_color_ok = True
if quality.lower() == Constants.TEXT_COLOR: if quality.lower() == Constants.TEXT_COLOR:
text_color_ok = True text_color_ok = True
self.__forecast_labels.set( self.__space_weather_labels.set(
"text_color", "text_color",
color color
) )
if color_len == 2: if color_len == 2:
if quality.lower() == Constants.LABEL_ON_COLOR: if quality.lower() == Constants.LABEL_ON_COLOR:
switch_on_color_ok = True switch_on_color_ok = True
self.__forecast_labels.set( self.__space_weather_labels.set(
"switch_on_colors", "switch_on_colors",
color color
) )
if quality.lower() == Constants.LABEL_OFF_COLOR: if quality.lower() == Constants.LABEL_OFF_COLOR:
switch_off_color_ok = True switch_off_color_ok = True
self.__forecast_labels.set( self.__space_weather_labels.set(
"switch_off_colors", "switch_off_colors",
color color
) )
@@ -280,17 +280,17 @@ class Theme(object):
self.__parent.inactive_color = ThemeConstants.DEFAULT_INACTIVE_COLOR self.__parent.inactive_color = ThemeConstants.DEFAULT_INACTIVE_COLOR
if not (switch_on_color_ok and switch_off_color_ok): if not (switch_on_color_ok and switch_off_color_ok):
self.__forecast_labels.set( self.__space_weather_labels.set(
"switch_on_colors", "switch_on_colors",
ThemeConstants.DEFAULT_ON_COLORS ThemeConstants.DEFAULT_ON_COLORS
) )
self.__forecast_labels.set( self.__space_weather_labels.set(
"switch_off_colors", "switch_off_colors",
ThemeConstants.DEFAULT_OFF_COLORS ThemeConstants.DEFAULT_OFF_COLORS
) )
if not text_color_ok: if not text_color_ok:
self.__forecast_labels.set( self.__space_weather_labels.set(
"text_color", "text_color",
ThemeConstants.DEFAULT_TEXT_COLOR ThemeConstants.DEFAULT_TEXT_COLOR
) )
@@ -305,7 +305,7 @@ class Theme(object):
except Exception: except Exception:
pass pass
def initialize(self): def start(self):
current_theme_file = os.path.join( current_theme_file = os.path.join(
ThemeConstants.FOLDER, ThemeConstants.FOLDER,
ThemeConstants.CURRENT ThemeConstants.CURRENT

View File

@@ -66,7 +66,7 @@ class DownloadThread(_BaseDownloadThread):
self.status = ThreadStatus.OK self.status = ThreadStatus.OK
class UpadteSpaceWeatherThread(_BaseDownloadThread): class UpdateSpaceWeatherThread(_BaseDownloadThread):
__properties = ("xray", "prot_el", "ak_index", "sgas", "geo_storm") __properties = ("xray", "prot_el", "ak_index", "sgas", "geo_storm")
@@ -79,12 +79,12 @@ class UpadteSpaceWeatherThread(_BaseDownloadThread):
return await resp.read() return await resp.read()
async def __download_property(self, session, property_name): 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) data = await self.__download_resource(session, link)
setattr(self.__space_weather_data, property_name, str(data, 'utf-8')) setattr(self.__space_weather_data, property_name, str(data, 'utf-8'))
async def __download_image(self, session, n): 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) self.__space_weather_data.images[n].loadFromData(im)
async def __download_resources(self, *links): async def __download_resources(self, *links):
@@ -96,7 +96,7 @@ class UpadteSpaceWeatherThread(_BaseDownloadThread):
asyncio.create_task(self.__download_property(session, p)) asyncio.create_task(self.__download_property(session, p))
) )
tot_images = range(len(Constants.FORECAST_IMGS)) tot_images = range(len(Constants.SPACE_WEATHER_IMGS))
t1 = [] t1 = []
for im_number in tot_images: for im_number in tot_images:
t1.append( t1.append(