Refactoring
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -3,7 +3,9 @@ Data
|
|||||||
.ipynb_checkpoints
|
.ipynb_checkpoints
|
||||||
*.ipynb
|
*.ipynb
|
||||||
wav_converter.py
|
wav_converter.py
|
||||||
*.txt
|
to_do.txt
|
||||||
|
csv_info.txt
|
||||||
|
pyinstaller_cmd.txt
|
||||||
icons_imgs
|
icons_imgs
|
||||||
TestData
|
TestData
|
||||||
themes/.current_theme
|
themes/.current_theme
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from pydub import AudioSegment
|
|||||||
from pygame import mixer
|
from pygame import mixer
|
||||||
from PyQt5.QtCore import QTimer, QTimer, pyqtSlot, QObject
|
from PyQt5.QtCore import QTimer, QTimer, pyqtSlot, QObject
|
||||||
|
|
||||||
from utilities import Constants
|
import constants
|
||||||
import qtawesome as qta
|
import qtawesome as qta
|
||||||
|
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ class AudioPlayer(QObject): # Maybe useless inheriting from QObject
|
|||||||
def set_audio_player(self, fname = ""):
|
def set_audio_player(self, fname = ""):
|
||||||
self.__first_call = True
|
self.__first_call = True
|
||||||
self.__reset_audio_widget()
|
self.__reset_audio_widget()
|
||||||
full_name = os.path.join(Constants.DATA_FOLDER, Constants.AUDIO_FOLDER, fname + '.ogg')
|
full_name = os.path.join(constants.DATA_FOLDER, constants.AUDIO_FOLDER, fname + '.ogg')
|
||||||
if os.path.exists(full_name):
|
if os.path.exists(full_name):
|
||||||
self.__play.setEnabled(True)
|
self.__play.setEnabled(True)
|
||||||
self.__audio_file = full_name
|
self.__audio_file = full_name
|
||||||
|
|||||||
168
constants.py
Normal file
168
constants.py
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
from collections import namedtuple
|
||||||
|
from enum import Enum, auto
|
||||||
|
|
||||||
|
class Ftype(object):
|
||||||
|
FREQ = "freq"
|
||||||
|
BAND = "band"
|
||||||
|
|
||||||
|
class ChecksumWhat(Enum):
|
||||||
|
FOLDER = auto()
|
||||||
|
DB = auto()
|
||||||
|
|
||||||
|
class Theme(object):
|
||||||
|
FOLDER = "themes"
|
||||||
|
EXTENSION = ".qss"
|
||||||
|
ICONS_FOLDER = "icons"
|
||||||
|
DEFAULT = "1-system"
|
||||||
|
CURRENT = ".current_theme"
|
||||||
|
COLORS = "colors.txt"
|
||||||
|
COLOR_SEPARATOR = "="
|
||||||
|
DEFAULT_ACTIVE_COLOR = "#39eaff"
|
||||||
|
DEFAULT_INACTIVE_COLOR = "#9f9f9f"
|
||||||
|
|
||||||
|
class Messages(object):
|
||||||
|
NO_DB_AVAIL = "No database available.\nGo to Updates->Update database."
|
||||||
|
NO_DB = "No database"
|
||||||
|
THEME_NOT_FOUND = "Theme not found"
|
||||||
|
MISSING_THEME = "Missing theme in " + Theme.FOLDER + " folder."
|
||||||
|
NO_CONNECTION = "No internet connection"
|
||||||
|
NO_CONNECTION_MSG = "Unable to establish an internet connection."
|
||||||
|
BAD_DOWNLOAD = "Something went wrong"
|
||||||
|
BAD_DOWNLOAD_MSG = "Something went wrong with the downaload.\nCheck your internet connection and try again."
|
||||||
|
BAD_FILE = "Bad file detected"
|
||||||
|
BAD_FILE_MSG = "The downloaded file seems to be corrupted.\nThe old database has not been deleted and\nthe downloaded file has been discarded."
|
||||||
|
|
||||||
|
class Signal(object):
|
||||||
|
NAME = "name"
|
||||||
|
INF_FREQ = "inf_freq"
|
||||||
|
SUP_FREQ = "sup_freq"
|
||||||
|
MODE = "mode"
|
||||||
|
INF_BAND = "inf_band"
|
||||||
|
SUP_BAND = "sup_band"
|
||||||
|
LOCATION = "location"
|
||||||
|
URL = "url"
|
||||||
|
DESCRIPTION = "description"
|
||||||
|
MODULATION = "modulation"
|
||||||
|
CATEGORY_CODE = "category_code"
|
||||||
|
ACF = "acf"
|
||||||
|
WIKI_CLICKED = "url_clicked"
|
||||||
|
|
||||||
|
class Database(object):
|
||||||
|
LINK_LOC = "https://aresvalley.com/Storage/Artemis/Database/data.zip"
|
||||||
|
LINK_REF = "https://aresvalley.com/Storage/Artemis/Database/data.zip.log"
|
||||||
|
NAME = "db.csv"
|
||||||
|
NAMES = (Signal.NAME,
|
||||||
|
Signal.INF_FREQ,
|
||||||
|
Signal.SUP_FREQ,
|
||||||
|
Signal.MODE,
|
||||||
|
Signal.INF_BAND,
|
||||||
|
Signal.SUP_BAND,
|
||||||
|
Signal.LOCATION,
|
||||||
|
Signal.URL,
|
||||||
|
Signal.DESCRIPTION,
|
||||||
|
Signal.MODULATION,
|
||||||
|
Signal.CATEGORY_CODE,
|
||||||
|
Signal.ACF,)
|
||||||
|
DELIMITER = "*"
|
||||||
|
STRINGS = (Signal.INF_FREQ,
|
||||||
|
Signal.SUP_FREQ,
|
||||||
|
Signal.MODE,
|
||||||
|
Signal.INF_BAND,
|
||||||
|
Signal.SUP_BAND,
|
||||||
|
Signal.CATEGORY_CODE,)
|
||||||
|
|
||||||
|
SEARCH_LABEL_IMG = "search_icon.png"
|
||||||
|
VOLUME_LABEL_IMG = "volume.png"
|
||||||
|
DATA_FOLDER = "Data"
|
||||||
|
SPECTRA_FOLDER = "Spectra"
|
||||||
|
SPECTRA_EXT = ".png"
|
||||||
|
AUDIO_FOLDER = "Audio"
|
||||||
|
ACTIVE = "active"
|
||||||
|
INACTIVE = "inactive"
|
||||||
|
NOT_AVAILABLE = "spectrumnotavailable.png"
|
||||||
|
NOT_SELECTED = "nosignalselected.png"
|
||||||
|
__Band = namedtuple("Band", ["lower", "upper"])
|
||||||
|
__ELF = __Band(0, 30) # Formally it is (3, 30) Hz.
|
||||||
|
__SLF = __Band(30, 300)
|
||||||
|
__ULF = __Band(300, 3000)
|
||||||
|
__VLF = __Band(3000, 30000)
|
||||||
|
__LF = __Band(30 * 10**3, 300 * 10**3)
|
||||||
|
__MF = __Band(300 * 10 ** 3, 3000 * 10**3)
|
||||||
|
__HF = __Band(3 * 10**6, 30 * 10**6)
|
||||||
|
__VHF = __Band(30 * 10**6, 300 * 10**6)
|
||||||
|
__UHF = __Band(300 * 10**6, 3000 * 10**6)
|
||||||
|
__SHF = __Band(3 * 10**9, 30 * 10**9)
|
||||||
|
__EHF = __Band(30 * 10**9, 300 * 10**9)
|
||||||
|
BANDS = (__ELF, __SLF, __ULF, __VLF, __LF, __MF, __HF, __VHF, __UHF, __SHF, __EHF)
|
||||||
|
CONVERSION_FACTORS = {"Hz" : 1,
|
||||||
|
"kHz": 1000,
|
||||||
|
"MHz": 1000000,
|
||||||
|
"GHz": 1000000000}
|
||||||
|
MODES = {"FM": ("NFM", "WFM"),
|
||||||
|
"AM": (),
|
||||||
|
"CW": (),
|
||||||
|
"SK": ("FSK", "PSK", "MSK"),
|
||||||
|
"SB": ("LSB", "USB", "DSB"),
|
||||||
|
"Chirp Spread Spectrum": (),
|
||||||
|
"FHSS-TDM": (),
|
||||||
|
"RAW": (),
|
||||||
|
"SC-FDMA": (),}
|
||||||
|
APPLY = "Apply"
|
||||||
|
REMOVE = "Remove"
|
||||||
|
UNKNOWN = "N/A"
|
||||||
|
MODULATIONS = ("8VSB",
|
||||||
|
"AFSK",
|
||||||
|
"AM",
|
||||||
|
"BFSK",
|
||||||
|
"C4FM",
|
||||||
|
"CDMA",
|
||||||
|
"COFDM",
|
||||||
|
"CW",
|
||||||
|
"FFSK",
|
||||||
|
"FM",
|
||||||
|
"FMCW",
|
||||||
|
"FMOP",
|
||||||
|
"FSK",
|
||||||
|
"GFSK",
|
||||||
|
"GMSK",
|
||||||
|
"IFK",
|
||||||
|
"MFSK",
|
||||||
|
"MSK",
|
||||||
|
"OFDM",
|
||||||
|
"OOK",
|
||||||
|
"PAM",
|
||||||
|
"PPM",
|
||||||
|
"PSK",
|
||||||
|
"QAM",
|
||||||
|
"TDMA",)
|
||||||
|
LOCATIONS = (UNKNOWN,
|
||||||
|
"Australia",
|
||||||
|
"Canada",
|
||||||
|
"Central Europe",
|
||||||
|
"China",
|
||||||
|
"Cyprus",
|
||||||
|
"Eastern Europe",
|
||||||
|
"Europe",
|
||||||
|
"Europe, japan and Asia",
|
||||||
|
"Exmouth, Australia",
|
||||||
|
"Finland",
|
||||||
|
"France",
|
||||||
|
"Germany",
|
||||||
|
"Home Base Mobile , AL",
|
||||||
|
"Hungary",
|
||||||
|
"Iran",
|
||||||
|
"Israel",
|
||||||
|
"Japan",
|
||||||
|
"LaMour, North Dakota",
|
||||||
|
"Lualualei, Hawaii",
|
||||||
|
"North America",
|
||||||
|
"North Korea",
|
||||||
|
"Poland",
|
||||||
|
"Romania",
|
||||||
|
"Ruda, Sweden",
|
||||||
|
"UK",
|
||||||
|
"United Kingdom",
|
||||||
|
"United States",
|
||||||
|
"Varberg, Sweden",
|
||||||
|
"World Wide",
|
||||||
|
"Worldwide",)
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>400</width>
|
<width>400</width>
|
||||||
<height>151</height>
|
<height>137</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Downloading database
|
<string>Downloading database
|
||||||
Please wait</string>
|
Please wait...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignCenter</set>
|
<set>Qt::AlignCenter</set>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
from PyQt5 import uic
|
from PyQt5 import uic
|
||||||
from PyQt5.QtCore import Qt, pyqtSlot
|
from PyQt5.QtCore import Qt, pyqtSlot
|
||||||
from PyQt5.QtWidgets import QWidget, QMessageBox
|
from PyQt5.QtWidgets import QWidget
|
||||||
from threads import DownloadThread, ThreadStatus
|
from threads import DownloadThread, ThreadStatus
|
||||||
|
from utilities import throwable_message
|
||||||
|
from constants import Messages
|
||||||
|
|
||||||
Ui_Download_window, _ = uic.loadUiType("download_db_window.ui")
|
Ui_Download_window, _ = uic.loadUiType("download_db_window.ui")
|
||||||
|
|
||||||
@@ -17,24 +19,19 @@ class DownloadWindow(QWidget, Ui_Download_window):
|
|||||||
# Qt.WindowStaysOnTopHint
|
# Qt.WindowStaysOnTopHint
|
||||||
)
|
)
|
||||||
self.everything_ok = True
|
self.everything_ok = True
|
||||||
self.no_internet_msg = QMessageBox(self)
|
|
||||||
self.no_internet_msg.setWindowTitle("No internet connection")
|
|
||||||
self.no_internet_msg.setText("Unable to establish an internet connection.")
|
|
||||||
# self.no_internet_msg.buttonClicked.connect(self.close)
|
|
||||||
self.no_internet_msg.finished.connect(self.close)
|
|
||||||
|
|
||||||
self.bad_db_download_msg = QMessageBox(self)
|
self.no_internet_msg = throwable_message(self, title = Messages.NO_CONNECTION,
|
||||||
self.bad_db_download_msg.setWindowTitle("Something wrong")
|
text = Messages.NO_CONNECTION_MSG,
|
||||||
self.bad_db_download_msg.setText("""Something went wrong with the downaload.
|
connection = self.close)
|
||||||
Check your internet connection and try again.""")
|
|
||||||
self.bad_db_download_msg.finished.connect(self.close)
|
|
||||||
|
|
||||||
self.bad_file_msg = QMessageBox(self)
|
self.bad_db_download_msg = throwable_message(self, title = Messages.BAD_DOWNLOAD,
|
||||||
self.bad_file_msg.setWindowTitle("Bad file detected")
|
text = Messages.BAD_DOWNLOAD_MSG,
|
||||||
self.bad_file_msg.setText("""The downloaded file seems to be corrupted.
|
connection = self.close)
|
||||||
The old database has not been deleted and
|
|
||||||
the downloaded file has been discarded.""")
|
# Never used (should exploit the checksum check for the single file)
|
||||||
self.bad_file_msg.finished.connect(self.close)
|
self.bad_file_msg = throwable_message(self, title = Messages.BAD_FILE,
|
||||||
|
text = Messages.BAD_FILE_MSG,
|
||||||
|
connection = self.close)
|
||||||
|
|
||||||
self.download_thread = DownloadThread()
|
self.download_thread = DownloadThread()
|
||||||
self.download_thread.finished.connect(self.wait_close)
|
self.download_thread.finished.connect(self.wait_close)
|
||||||
@@ -42,8 +39,6 @@ class DownloadWindow(QWidget, Ui_Download_window):
|
|||||||
self.cancel_btn.clicked.connect(self.terminate_process)
|
self.cancel_btn.clicked.connect(self.terminate_process)
|
||||||
|
|
||||||
def show_no_connection_warning(self):
|
def show_no_connection_warning(self):
|
||||||
self.bad_db_download_msg.setText(f"""Unable to correctly download the database.
|
|
||||||
Reason: {self.download_thread.reason}""")
|
|
||||||
self.no_internet_msg.show()
|
self.no_internet_msg.show()
|
||||||
self.everything_ok = False
|
self.everything_ok = False
|
||||||
|
|
||||||
@@ -51,6 +46,10 @@ class DownloadWindow(QWidget, Ui_Download_window):
|
|||||||
self.bad_db_download_msg.show()
|
self.bad_db_download_msg.show()
|
||||||
self.everything_ok = False
|
self.everything_ok = False
|
||||||
|
|
||||||
|
def show_bad_file_warning(self):
|
||||||
|
self.bad_file_msg.show()
|
||||||
|
self.everything_ok = False
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def terminate_process(self):
|
def terminate_process(self):
|
||||||
if self.download_thread.isRunning():
|
if self.download_thread.isRunning():
|
||||||
@@ -65,7 +64,7 @@ class DownloadWindow(QWidget, Ui_Download_window):
|
|||||||
elif self.download_thread.status == ThreadStatus.NO_CONNECTION_ERR:
|
elif self.download_thread.status == ThreadStatus.NO_CONNECTION_ERR:
|
||||||
self.show_no_connection_warning()
|
self.show_no_connection_warning()
|
||||||
elif self.download_thread.status == ThreadStatus.BAD_DOWNLOAD_ERR:
|
elif self.download_thread.status == ThreadStatus.BAD_DOWNLOAD_ERR:
|
||||||
self.show_bad_download_warning
|
self.show_bad_download_warning()
|
||||||
else:
|
else:
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
|
|||||||
282
main.py
282
main.py
@@ -9,7 +9,6 @@ from pandas import read_csv
|
|||||||
from PyQt5.QtWidgets import (QMainWindow,
|
from PyQt5.QtWidgets import (QMainWindow,
|
||||||
QApplication,
|
QApplication,
|
||||||
QAction,
|
QAction,
|
||||||
QMessageBox,
|
|
||||||
qApp,
|
qApp,
|
||||||
QDesktopWidget,
|
QDesktopWidget,
|
||||||
QListWidgetItem,
|
QListWidgetItem,
|
||||||
@@ -27,17 +26,23 @@ from audio_player import AudioPlayer
|
|||||||
from double_text_button import DoubleTextButton
|
from double_text_button import DoubleTextButton
|
||||||
from download_window import DownloadWindow
|
from download_window import DownloadWindow
|
||||||
|
|
||||||
|
import constants
|
||||||
|
|
||||||
from utilities import (Constants,
|
from utilities import (reset_apply_remove_btn,
|
||||||
reset_apply_remove_btn,
|
|
||||||
throwable_message,
|
throwable_message,
|
||||||
is_valid_html_color,)
|
is_valid_html_color,
|
||||||
|
connect_to,
|
||||||
|
filters_ok,
|
||||||
|
is_undef_freq,
|
||||||
|
is_undef_band,
|
||||||
|
change_unit,
|
||||||
|
format_numbers)
|
||||||
|
|
||||||
qt_creator_file = "main_window.ui"
|
qt_creator_file = "main_window.ui"
|
||||||
Ui_MainWindow, _ = uic.loadUiType(qt_creator_file)
|
Ui_MainWindow, _ = uic.loadUiType(qt_creator_file)
|
||||||
|
|
||||||
class MyApp(QMainWindow, Ui_MainWindow):
|
|
||||||
|
|
||||||
|
class MyApp(QMainWindow, Ui_MainWindow):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
@@ -49,8 +54,8 @@ class MyApp(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.active_color = Constants.ACTIVE_COLOR
|
self.active_color = constants.Theme.DEFAULT_ACTIVE_COLOR
|
||||||
self.inactive_color = Constants.INACTIVE_COLOR
|
self.inactive_color = constants.Theme.DEFAULT_INACTIVE_COLOR
|
||||||
|
|
||||||
# Manage frequency filters.
|
# Manage frequency filters.
|
||||||
self.frequency_filters_btns = (
|
self.frequency_filters_btns = (
|
||||||
@@ -67,7 +72,7 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
self.ehf_filter_btn,
|
self.ehf_filter_btn,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.connect_to(
|
connect_to(
|
||||||
objects_to_connect = [self.lower_freq_spinbox.valueChanged,
|
objects_to_connect = [self.lower_freq_spinbox.valueChanged,
|
||||||
self.upper_freq_spinbox.valueChanged,
|
self.upper_freq_spinbox.valueChanged,
|
||||||
self.lower_freq_filter_unit.currentTextChanged,
|
self.lower_freq_filter_unit.currentTextChanged,
|
||||||
@@ -80,7 +85,7 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
self.upper_freq_spinbox]
|
self.upper_freq_spinbox]
|
||||||
)
|
)
|
||||||
|
|
||||||
self.connect_to(
|
connect_to(
|
||||||
objects_to_connect = [self.lower_freq_spinbox.valueChanged,
|
objects_to_connect = [self.lower_freq_spinbox.valueChanged,
|
||||||
self.upper_freq_spinbox.valueChanged,
|
self.upper_freq_spinbox.valueChanged,
|
||||||
self.lower_freq_filter_unit.currentTextChanged,
|
self.lower_freq_filter_unit.currentTextChanged,
|
||||||
@@ -117,7 +122,7 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
self.upper_freq_confidence)
|
self.upper_freq_confidence)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.apply_remove_freq_filter_btn.set_texts(Constants.APPLY, Constants.REMOVE)
|
self.apply_remove_freq_filter_btn.set_texts(constants.APPLY, constants.REMOVE)
|
||||||
self.apply_remove_freq_filter_btn.set_slave_filters(
|
self.apply_remove_freq_filter_btn.set_slave_filters(
|
||||||
[
|
[
|
||||||
*self.frequency_filters_btns,
|
*self.frequency_filters_btns,
|
||||||
@@ -139,11 +144,11 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
self.apply_remove_freq_filter_btn.clicked.connect(self.display_signals)
|
self.apply_remove_freq_filter_btn.clicked.connect(self.display_signals)
|
||||||
self.reset_frequency_filters_btn.clicked.connect(partial(self.reset_fb_filters, 'freq'))
|
self.reset_frequency_filters_btn.clicked.connect(partial(self.reset_fb_filters, constants.Ftype.FREQ))
|
||||||
|
|
||||||
# Manage bandwidth filters.
|
# Manage bandwidth filters.
|
||||||
|
|
||||||
self.connect_to(
|
connect_to(
|
||||||
objects_to_connect = [self.lower_band_spinbox.valueChanged,
|
objects_to_connect = [self.lower_band_spinbox.valueChanged,
|
||||||
self.upper_band_spinbox.valueChanged,
|
self.upper_band_spinbox.valueChanged,
|
||||||
self.lower_band_filter_unit.currentTextChanged,
|
self.lower_band_filter_unit.currentTextChanged,
|
||||||
@@ -156,7 +161,7 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
self.upper_band_spinbox]
|
self.upper_band_spinbox]
|
||||||
)
|
)
|
||||||
|
|
||||||
self.connect_to(
|
connect_to(
|
||||||
objects_to_connect = [self.lower_band_spinbox.valueChanged,
|
objects_to_connect = [self.lower_band_spinbox.valueChanged,
|
||||||
self.upper_band_spinbox.valueChanged,
|
self.upper_band_spinbox.valueChanged,
|
||||||
self.lower_band_filter_unit.currentTextChanged,
|
self.lower_band_filter_unit.currentTextChanged,
|
||||||
@@ -193,7 +198,7 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
self.upper_band_confidence)
|
self.upper_band_confidence)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.apply_remove_band_filter_btn.set_texts(Constants.APPLY, Constants.REMOVE)
|
self.apply_remove_band_filter_btn.set_texts(constants.APPLY, constants.REMOVE)
|
||||||
self.apply_remove_band_filter_btn.set_slave_filters(
|
self.apply_remove_band_filter_btn.set_slave_filters(
|
||||||
[
|
[
|
||||||
self.include_undef_bands,
|
self.include_undef_bands,
|
||||||
@@ -214,7 +219,7 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
self.apply_remove_band_filter_btn.clicked.connect(self.display_signals)
|
self.apply_remove_band_filter_btn.clicked.connect(self.display_signals)
|
||||||
self.reset_band_filters_btn.clicked.connect(partial(self.reset_fb_filters, 'band'))
|
self.reset_band_filters_btn.clicked.connect(partial(self.reset_fb_filters, constants.Ftype.BAND))
|
||||||
|
|
||||||
# Manage category filters
|
# Manage category filters
|
||||||
|
|
||||||
@@ -237,7 +242,7 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
self.number_stations_btn,
|
self.number_stations_btn,
|
||||||
self.time_signal_btn,]
|
self.time_signal_btn,]
|
||||||
|
|
||||||
self.apply_remove_cat_filter_btn.set_texts(Constants.APPLY, Constants.REMOVE)
|
self.apply_remove_cat_filter_btn.set_texts(constants.APPLY, constants.REMOVE)
|
||||||
self.apply_remove_cat_filter_btn.set_slave_filters([*self.cat_filter_btns,
|
self.apply_remove_cat_filter_btn.set_slave_filters([*self.cat_filter_btns,
|
||||||
self.cat_at_least_one,
|
self.cat_at_least_one,
|
||||||
self.cat_all])
|
self.cat_all])
|
||||||
@@ -283,16 +288,16 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
self.set_mode_tree_widget()
|
self.set_mode_tree_widget()
|
||||||
self.mode_tree_widget.itemSelectionChanged.connect(self.manage_mode_selections)
|
self.mode_tree_widget.itemSelectionChanged.connect(self.manage_mode_selections)
|
||||||
self.reset_mode_filters_btn.clicked.connect(self.reset_mode_filters)
|
self.reset_mode_filters_btn.clicked.connect(self.reset_mode_filters)
|
||||||
self.apply_remove_mode_filter_btn.set_texts(Constants.APPLY, Constants.REMOVE)
|
self.apply_remove_mode_filter_btn.set_texts(constants.APPLY, constants.REMOVE)
|
||||||
self.apply_remove_mode_filter_btn.set_slave_filters([self.mode_tree_widget,
|
self.apply_remove_mode_filter_btn.set_slave_filters([self.mode_tree_widget,
|
||||||
self.include_unknown_modes_btn])
|
self.include_unknown_modes_btn])
|
||||||
self.apply_remove_mode_filter_btn.clicked.connect(self.display_signals)
|
self.apply_remove_mode_filter_btn.clicked.connect(self.display_signals)
|
||||||
|
|
||||||
# Set modulation filter screen.
|
# Set modulation filter screen.
|
||||||
|
|
||||||
self.modulation_list.addItems(Constants.MODULATIONS)
|
self.modulation_list.addItems(constants.MODULATIONS)
|
||||||
self.search_bar_modulation.textEdited.connect(self.show_matching_modulations)
|
self.search_bar_modulation.textEdited.connect(self.show_matching_modulations)
|
||||||
self.apply_remove_modulation_filter_btn.set_texts(Constants.APPLY, Constants.REMOVE)
|
self.apply_remove_modulation_filter_btn.set_texts(constants.APPLY, constants.REMOVE)
|
||||||
self.apply_remove_modulation_filter_btn.set_slave_filters([self.search_bar_modulation,
|
self.apply_remove_modulation_filter_btn.set_slave_filters([self.search_bar_modulation,
|
||||||
self.modulation_list])
|
self.modulation_list])
|
||||||
self.apply_remove_modulation_filter_btn.clicked.connect(self.display_signals)
|
self.apply_remove_modulation_filter_btn.clicked.connect(self.display_signals)
|
||||||
@@ -301,9 +306,9 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
# Set location filter screen.
|
# Set location filter screen.
|
||||||
|
|
||||||
self.locations_list.addItems(Constants.LOCATIONS)
|
self.locations_list.addItems(constants.LOCATIONS)
|
||||||
self.search_bar_location.textEdited.connect(self.show_matching_locations)
|
self.search_bar_location.textEdited.connect(self.show_matching_locations)
|
||||||
self.apply_remove_location_filter_btn.set_texts(Constants.APPLY, Constants.REMOVE)
|
self.apply_remove_location_filter_btn.set_texts(constants.APPLY, constants.REMOVE)
|
||||||
self.apply_remove_location_filter_btn.set_slave_filters([self.search_bar_location,
|
self.apply_remove_location_filter_btn.set_slave_filters([self.search_bar_location,
|
||||||
self.locations_list])
|
self.locations_list])
|
||||||
self.apply_remove_location_filter_btn.clicked.connect(self.display_signals)
|
self.apply_remove_location_filter_btn.clicked.connect(self.display_signals)
|
||||||
@@ -311,11 +316,9 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
self.locations_list.itemClicked.connect(self.remove_if_unselected_location)
|
self.locations_list.itemClicked.connect(self.remove_if_unselected_location)
|
||||||
|
|
||||||
# Find available themes.
|
# Find available themes.
|
||||||
self.default_images_folder = os.path.join(Constants.THEMES_FOLDER,
|
self.default_images_folder = os.path.join(constants.Theme.FOLDER,
|
||||||
Constants.DEFAULT_THEME,
|
constants.Theme.DEFAULT,
|
||||||
Constants.ICONS_FOLDER)
|
constants.Theme.ICONS_FOLDER)
|
||||||
# self.find_themes()
|
|
||||||
# self.set_theme()
|
|
||||||
|
|
||||||
# ##########################################################################################
|
# ##########################################################################################
|
||||||
|
|
||||||
@@ -357,10 +360,10 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
def find_themes(self):
|
def find_themes(self):
|
||||||
themes = []
|
themes = []
|
||||||
for theme_folder in os.listdir(Constants.THEMES_FOLDER):
|
for theme_folder in os.listdir(constants.Theme.FOLDER):
|
||||||
relative_folder = os.path.join(Constants.THEMES_FOLDER, theme_folder)
|
relative_folder = os.path.join(constants.Theme.FOLDER, theme_folder)
|
||||||
if os.path.isdir(os.path.abspath(relative_folder)):
|
if os.path.isdir(os.path.abspath(relative_folder)):
|
||||||
relative_folder = os.path.join(Constants.THEMES_FOLDER, theme_folder)
|
relative_folder = os.path.join(constants.Theme.FOLDER, theme_folder)
|
||||||
themes.append(relative_folder)
|
themes.append(relative_folder)
|
||||||
for theme in themes:
|
for theme in themes:
|
||||||
theme_name = '&' + ' '.join(
|
theme_name = '&' + ' '.join(
|
||||||
@@ -382,26 +385,26 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
try:
|
try:
|
||||||
with open(os.path.join(
|
with open(os.path.join(
|
||||||
theme_path,
|
theme_path,
|
||||||
os.path.basename(theme_path).split('-')[1] + Constants.THEME_EXTENSION)
|
os.path.basename(theme_path).split('-')[1] + constants.Theme.EXTENSION)
|
||||||
) as stylesheet:
|
) as stylesheet:
|
||||||
style = stylesheet.read()
|
style = stylesheet.read()
|
||||||
self.setStyleSheet(style)
|
self.setStyleSheet(style)
|
||||||
self.download_window.setStyleSheet(style)
|
self.download_window.setStyleSheet(style)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
throwable_message(self, title = "Theme not found",
|
throwable_message(self, title = constants.Messages.THEME_NOT_FOUND,
|
||||||
text = f"Missing theme in {Constants.THEMES_FOLDER} folder.").show()
|
text = constants.Messages.MISSING_THEME).show()
|
||||||
else:
|
else:
|
||||||
icons_path = os.path.join(theme_path, Constants.ICONS_FOLDER)
|
icons_path = os.path.join(theme_path, constants.Theme.ICONS_FOLDER)
|
||||||
default_icons_path = os.path.join(Constants.THEMES_FOLDER, Constants.DEFAULT_THEME, Constants.ICONS_FOLDER)
|
default_icons_path = os.path.join(constants.Theme.FOLDER, constants.Theme.DEFAULT, constants.Theme.ICONS_FOLDER)
|
||||||
|
|
||||||
if os.path.exists(os.path.join(icons_path, Constants.NOT_SELECTED)) and \
|
if os.path.exists(os.path.join(icons_path, constants.NOT_SELECTED)) and \
|
||||||
os.path.exists(os.path.join(icons_path, Constants.NOT_AVAILABLE)):
|
os.path.exists(os.path.join(icons_path, constants.NOT_AVAILABLE)):
|
||||||
self.default_images_folder = icons_path
|
self.default_images_folder = icons_path
|
||||||
else:
|
else:
|
||||||
self.default_images_folder = default_icons_path
|
self.default_images_folder = default_icons_path
|
||||||
|
|
||||||
path_to_search_label = os.path.join(icons_path, Constants.SEARCH_LABEL_IMG)
|
path_to_search_label = os.path.join(icons_path, constants.SEARCH_LABEL_IMG)
|
||||||
default_search_label = os.path.join(default_icons_path, Constants.SEARCH_LABEL_IMG)
|
default_search_label = os.path.join(default_icons_path, constants.SEARCH_LABEL_IMG)
|
||||||
|
|
||||||
if os.path.exists(path_to_search_label):
|
if os.path.exists(path_to_search_label):
|
||||||
self.search_label.setPixmap(QPixmap(path_to_search_label))
|
self.search_label.setPixmap(QPixmap(path_to_search_label))
|
||||||
@@ -416,8 +419,8 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
self.modulation_search_label.setScaledContents(True)
|
self.modulation_search_label.setScaledContents(True)
|
||||||
self.location_search_label.setScaledContents(True)
|
self.location_search_label.setScaledContents(True)
|
||||||
|
|
||||||
path_to_volume_label = os.path.join(icons_path, Constants.VOLUME_LABEL_IMG)
|
path_to_volume_label = os.path.join(icons_path, constants.VOLUME_LABEL_IMG)
|
||||||
default_volume_label = os.path.join(default_icons_path, Constants.VOLUME_LABEL_IMG)
|
default_volume_label = os.path.join(default_icons_path, constants.VOLUME_LABEL_IMG)
|
||||||
|
|
||||||
if os.path.exists(path_to_volume_label):
|
if os.path.exists(path_to_volume_label):
|
||||||
self.volume_label.setPixmap(QPixmap(path_to_volume_label))
|
self.volume_label.setPixmap(QPixmap(path_to_volume_label))
|
||||||
@@ -426,7 +429,7 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
self.volume_label.setScaledContents(True)
|
self.volume_label.setScaledContents(True)
|
||||||
|
|
||||||
path_to_colors = os.path.join(theme_path, Constants.THEME_COLORS)
|
path_to_colors = os.path.join(theme_path, constants.Theme.COLORS)
|
||||||
active_color_ok = False
|
active_color_ok = False
|
||||||
inactive_color_ok = False
|
inactive_color_ok = False
|
||||||
valid_format = False
|
valid_format = False
|
||||||
@@ -435,36 +438,36 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
valid_file = True
|
valid_file = True
|
||||||
with open(path_to_colors, "r") as colors_file:
|
with open(path_to_colors, "r") as colors_file:
|
||||||
for line in colors_file:
|
for line in colors_file:
|
||||||
if '=' in line:
|
if constants.Theme.COLOR_SEPARATOR in line:
|
||||||
valid_format = True
|
valid_format = True
|
||||||
quality, color = line.split("=")
|
quality, color = line.split(constants.Theme.COLOR_SEPARATOR)
|
||||||
color = color.rstrip()
|
color = color.rstrip()
|
||||||
if quality == "active" and is_valid_html_color(color):
|
if quality.lower() == constants.ACTIVE and is_valid_html_color(color):
|
||||||
self.active_color = color
|
self.active_color = color
|
||||||
active_color_ok = True
|
active_color_ok = True
|
||||||
if quality == "inactive" and is_valid_html_color(color):
|
if quality.lower() == constants.INACTIVE and is_valid_html_color(color):
|
||||||
self.inactive_color = color
|
self.inactive_color = color
|
||||||
inactive_color_ok = True
|
inactive_color_ok = True
|
||||||
|
|
||||||
if not all([valid_file, valid_format, active_color_ok, inactive_color_ok]):
|
if not all([valid_file, valid_format, active_color_ok, inactive_color_ok]):
|
||||||
self.active_color = Constants.ACTIVE_COLOR
|
self.active_color = constants.Theme.DEFAULT_ACTIVE_COLOR
|
||||||
self.inactive_color = Constants.INACTIVE_COLOR
|
self.inactive_color = constants.Theme.DEFAULT_INACTIVE_COLOR
|
||||||
|
|
||||||
self.audio_widget.refresh_btns_colors(self.active_color, self.inactive_color)
|
self.audio_widget.refresh_btns_colors(self.active_color, self.inactive_color)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(os.path.join(Constants.THEMES_FOLDER,
|
with open(os.path.join(constants.Theme.FOLDER,
|
||||||
Constants.CURRENT_THEME), "w") as current_theme:
|
constants.Theme.CURRENT), "w") as current_theme:
|
||||||
current_theme.write(theme_path)
|
current_theme.write(theme_path)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def set_theme(self):
|
def set_theme(self):
|
||||||
current_theme_file = os.path.join(Constants.THEMES_FOLDER, Constants.CURRENT_THEME)
|
current_theme_file = os.path.join(constants.Theme.FOLDER, constants.Theme.CURRENT)
|
||||||
if os.path.exists(current_theme_file):
|
if os.path.exists(current_theme_file):
|
||||||
with open(current_theme_file) as current_theme:
|
with open(current_theme_file) as current_theme:
|
||||||
theme = current_theme.read()
|
theme = current_theme.read()
|
||||||
if theme != Constants.DEFAULT_THEME:
|
if theme != constants.Theme.DEFAULT:
|
||||||
self.change_theme(theme)
|
self.change_theme(theme)
|
||||||
|
|
||||||
@pyqtSlot(QListWidgetItem)
|
@pyqtSlot(QListWidgetItem)
|
||||||
@@ -494,7 +497,7 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
item.setHidden(True)
|
item.setHidden(True)
|
||||||
|
|
||||||
def set_mode_tree_widget(self):
|
def set_mode_tree_widget(self):
|
||||||
for parent, children in Constants.MODES.items():
|
for parent, children in constants.MODES.items():
|
||||||
iparent = QTreeWidgetItem([parent])
|
iparent = QTreeWidgetItem([parent])
|
||||||
self.mode_tree_widget.addTopLevelItem(iparent)
|
self.mode_tree_widget.addTopLevelItem(iparent)
|
||||||
for child in children:
|
for child in children:
|
||||||
@@ -504,11 +507,11 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
def manage_mode_selections(self):
|
def manage_mode_selections(self):
|
||||||
selected_items = self.mode_tree_widget.selectedItems()
|
selected_items = self.mode_tree_widget.selectedItems()
|
||||||
parents = Constants.MODES.keys()
|
parents = constants.MODES.keys()
|
||||||
for parent in parents:
|
for parent in parents:
|
||||||
for item in selected_items:
|
for item in selected_items:
|
||||||
if parent == item.text(0):
|
if parent == item.text(0):
|
||||||
for i in range(len(Constants.MODES[parent])):
|
for i in range(len(constants.MODES[parent])):
|
||||||
item.child(i).setSelected(True)
|
item.child(i).setSelected(True)
|
||||||
|
|
||||||
def set_initial_size(self):
|
def set_initial_size(self):
|
||||||
@@ -571,32 +574,25 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
self.display_signals()
|
self.display_signals()
|
||||||
|
|
||||||
def load_db(self):
|
def load_db(self):
|
||||||
names = Constants.DB_NAMES
|
names = constants.Database.NAMES
|
||||||
try:
|
try:
|
||||||
self.db = read_csv(os.path.join(Constants.DATA_FOLDER, Constants.DB_NAME),
|
self.db = read_csv(os.path.join(constants.DATA_FOLDER, constants.Database.NAME),
|
||||||
sep = '*',
|
sep = constants.Database.DELIMITER,
|
||||||
header = None,
|
header = None,
|
||||||
index_col = 0,
|
index_col = 0,
|
||||||
dtype = {name : str for name in Constants.DB_STRINGS},
|
dtype = {name : str for name in constants.Database.STRINGS},
|
||||||
names = names,)
|
names = names,)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
self.search_bar.setDisabled(True)
|
self.search_bar.setDisabled(True)
|
||||||
box = QMessageBox(self)
|
throwable_message(self, title = constants.Messages.NO_DB,
|
||||||
box.setWindowTitle(Constants.Messages.NO_DB)
|
text = constants.Messages.NO_DB_AVAIL).show()
|
||||||
box.setText(Constants.Messages.NO_DB_AVAIL)
|
|
||||||
box.show()
|
|
||||||
else:
|
else:
|
||||||
self.signal_names = self.db.index
|
self.signal_names = self.db.index
|
||||||
self.total_signals = len(self.signal_names)
|
self.total_signals = len(self.signal_names)
|
||||||
self.db.fillna(Constants.UNKNOWN, inplace = True)
|
self.db.fillna(constants.UNKNOWN, inplace = True)
|
||||||
self.db[Constants.DB_WIKI_CLICKED] = False
|
self.db[constants.Signal.WIKI_CLICKED] = False
|
||||||
self.update_status_tip(self.total_signals)
|
self.update_status_tip(self.total_signals)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def connect_to(objects_to_connect, fun_to_connect, fun_args):
|
|
||||||
for signal in objects_to_connect:
|
|
||||||
signal.connect(partial(fun_to_connect, *fun_args))
|
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def set_min_value_upper_limit(self, lower_combo_box,
|
def set_min_value_upper_limit(self, lower_combo_box,
|
||||||
lower_spin_box,
|
lower_spin_box,
|
||||||
@@ -605,14 +601,13 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
if lower_spin_box.isEnabled():
|
if lower_spin_box.isEnabled():
|
||||||
unit_conversion = {'Hz' : ['kHz', 'MHz', 'GHz'],
|
unit_conversion = {'Hz' : ['kHz', 'MHz', 'GHz'],
|
||||||
'kHz': ['MHz', 'GHz'],
|
'kHz': ['MHz', 'GHz'],
|
||||||
'MHz': ['GHz']
|
'MHz': ['GHz']}
|
||||||
}
|
|
||||||
lower_units = lower_combo_box.currentText()
|
lower_units = lower_combo_box.currentText()
|
||||||
upper_units = upper_combo_box.currentText()
|
upper_units = upper_combo_box.currentText()
|
||||||
lower_value = lower_spin_box.value()
|
lower_value = lower_spin_box.value()
|
||||||
upper_value = upper_spin_box.value()
|
upper_value = upper_spin_box.value()
|
||||||
inf_limit = (lower_value * Constants.CONVERSION_FACTORS[lower_units]) \
|
inf_limit = (lower_value * constants.CONVERSION_FACTORS[lower_units]) \
|
||||||
// Constants.CONVERSION_FACTORS[upper_units]
|
// constants.CONVERSION_FACTORS[upper_units]
|
||||||
counter = 0
|
counter = 0
|
||||||
while inf_limit > upper_spin_box.maximum():
|
while inf_limit > upper_spin_box.maximum():
|
||||||
counter += 1
|
counter += 1
|
||||||
@@ -685,8 +680,6 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def display_signals(self):
|
def display_signals(self):
|
||||||
# for i in range(self.result_list.count()):
|
|
||||||
# self.result_list.item(i).setHidden(True)
|
|
||||||
text = self.search_bar.text()
|
text = self.search_bar.text()
|
||||||
available_signals = 0
|
available_signals = 0
|
||||||
for index, signal in enumerate(self.signal_names):
|
for index, signal in enumerate(self.signal_names):
|
||||||
@@ -712,7 +705,7 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def reset_fb_filters(self, ftype):
|
def reset_fb_filters(self, ftype):
|
||||||
if ftype != 'freq' and ftype != 'band':
|
if ftype != constants.Ftype.FREQ and ftype != constants.Ftype.BAND:
|
||||||
raise ValueError("Wrong ftype in function 'reset_fb_filters'")
|
raise ValueError("Wrong ftype in function 'reset_fb_filters'")
|
||||||
apply_remove_btn = getattr(self, 'apply_remove_' + ftype + '_filter_btn')
|
apply_remove_btn = getattr(self, 'apply_remove_' + ftype + '_filter_btn')
|
||||||
include_undef_btn = getattr(self, 'include_undef_' + ftype + 's')
|
include_undef_btn = getattr(self, 'include_undef_' + ftype + 's')
|
||||||
@@ -724,8 +717,8 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
upper_spinbox = getattr(self, 'upper_' + ftype + '_spinbox')
|
upper_spinbox = getattr(self, 'upper_' + ftype + '_spinbox')
|
||||||
lower_confidence = getattr(self, 'lower_' + ftype + '_confidence')
|
lower_confidence = getattr(self, 'lower_' + ftype + '_confidence')
|
||||||
upper_confidence = getattr(self, 'lower_' + ftype + '_confidence')
|
upper_confidence = getattr(self, 'lower_' + ftype + '_confidence')
|
||||||
default_val = 1 if ftype == 'freq' else 5000
|
default_val = 1 if ftype == constants.Ftype.FREQ else 5000
|
||||||
if ftype == 'freq':
|
if ftype == constants.Ftype.FREQ:
|
||||||
for f in self.frequency_filters_btns:
|
for f in self.frequency_filters_btns:
|
||||||
if f.isChecked():
|
if f.isChecked():
|
||||||
f.setChecked(False)
|
f.setChecked(False)
|
||||||
@@ -776,19 +769,19 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
def frequency_filters_ok(self, signal_name):
|
def frequency_filters_ok(self, signal_name):
|
||||||
if not self.apply_remove_freq_filter_btn.isChecked():
|
if not self.apply_remove_freq_filter_btn.isChecked():
|
||||||
return True
|
return True
|
||||||
undef_freq = self.is_undef_freq(self.db.loc[signal_name])
|
undef_freq = is_undef_freq(self.db.loc[signal_name])
|
||||||
if undef_freq:
|
if undef_freq:
|
||||||
if self.include_undef_freqs.isChecked():
|
if self.include_undef_freqs.isChecked():
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
signal_freqs = (int(self.db.at[signal_name, "inf_freq"]),
|
signal_freqs = (int(self.db.at[signal_name, constants.Signal.INF_FREQ]),
|
||||||
int(self.db.at[signal_name, "sup_freq"]))
|
int(self.db.at[signal_name, constants.Signal.SUP_FREQ]))
|
||||||
|
|
||||||
band_filter_ok = False
|
band_filter_ok = False
|
||||||
any_checked = False
|
any_checked = False
|
||||||
for btn, band_limits in zip(self.frequency_filters_btns, Constants.BANDS):
|
for btn, band_limits in zip(self.frequency_filters_btns, constants.BANDS):
|
||||||
if btn.isChecked():
|
if btn.isChecked():
|
||||||
any_checked = True
|
any_checked = True
|
||||||
if signal_freqs[0] < band_limits.upper and signal_freqs[1] >= band_limits.lower:
|
if signal_freqs[0] < band_limits.upper and signal_freqs[1] >= band_limits.lower:
|
||||||
@@ -796,12 +789,12 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
lower_limit_ok = True
|
lower_limit_ok = True
|
||||||
upper_limit_ok = True
|
upper_limit_ok = True
|
||||||
if self.activate_low_freq_filter_btn.isChecked():
|
if self.activate_low_freq_filter_btn.isChecked():
|
||||||
if not signal_freqs[1] >= self.filters_ok(self.lower_freq_spinbox,
|
if not signal_freqs[1] >= filters_ok(self.lower_freq_spinbox,
|
||||||
self.lower_freq_filter_unit,
|
self.lower_freq_filter_unit,
|
||||||
self.lower_freq_confidence, -1):
|
self.lower_freq_confidence, -1):
|
||||||
lower_limit_ok = False
|
lower_limit_ok = False
|
||||||
if self.activate_up_freq_filter_btn.isChecked():
|
if self.activate_up_freq_filter_btn.isChecked():
|
||||||
if not signal_freqs[0] < self.filters_ok(self.upper_freq_spinbox,
|
if not signal_freqs[0] < filters_ok(self.upper_freq_spinbox,
|
||||||
self.upper_freq_filter_unit,
|
self.upper_freq_filter_unit,
|
||||||
self.upper_freq_confidence):
|
self.upper_freq_confidence):
|
||||||
upper_limit_ok = False
|
upper_limit_ok = False
|
||||||
@@ -813,25 +806,25 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
def band_filters_ok(self, signal_name):
|
def band_filters_ok(self, signal_name):
|
||||||
if not self.apply_remove_band_filter_btn.isChecked():
|
if not self.apply_remove_band_filter_btn.isChecked():
|
||||||
return True
|
return True
|
||||||
undef_band = self.is_undef_band(self.db.loc[signal_name])
|
undef_band = is_undef_band(self.db.loc[signal_name])
|
||||||
if undef_band:
|
if undef_band:
|
||||||
if self.include_undef_bands.isChecked():
|
if self.include_undef_bands.isChecked():
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
signal_bands = (int(self.db.at[signal_name, "inf_band"]),
|
signal_bands = (int(self.db.at[signal_name, constants.Signal.INF_BAND]),
|
||||||
int(self.db.at[signal_name, "sup_band"]))
|
int(self.db.at[signal_name, constants.Signal.SUP_BAND]))
|
||||||
|
|
||||||
lower_limit_ok = True
|
lower_limit_ok = True
|
||||||
upper_limit_ok = True
|
upper_limit_ok = True
|
||||||
if self.activate_low_band_filter_btn.isChecked():
|
if self.activate_low_band_filter_btn.isChecked():
|
||||||
if not signal_bands[1] >= self.filters_ok(self.lower_band_spinbox,
|
if not signal_bands[1] >= filters_ok(self.lower_band_spinbox,
|
||||||
self.lower_band_filter_unit,
|
self.lower_band_filter_unit,
|
||||||
self.lower_band_confidence, -1):
|
self.lower_band_confidence, -1):
|
||||||
lower_limit_ok = False
|
lower_limit_ok = False
|
||||||
if self.activate_up_band_filter_btn.isChecked():
|
if self.activate_up_band_filter_btn.isChecked():
|
||||||
if not signal_bands[0] < self.filters_ok(self.upper_band_spinbox,
|
if not signal_bands[0] < filters_ok(self.upper_band_spinbox,
|
||||||
self.upper_band_filter_unit,
|
self.upper_band_filter_unit,
|
||||||
self.upper_band_confidence):
|
self.upper_band_confidence):
|
||||||
upper_limit_ok = False
|
upper_limit_ok = False
|
||||||
@@ -840,7 +833,7 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
def category_filters_ok(self, signal_name):
|
def category_filters_ok(self, signal_name):
|
||||||
if not self.apply_remove_cat_filter_btn.isChecked():
|
if not self.apply_remove_cat_filter_btn.isChecked():
|
||||||
return True
|
return True
|
||||||
cat_code = self.db.at[signal_name, 'category_code']
|
cat_code = self.db.at[signal_name, constants.Signal.CATEGORY_CODE]
|
||||||
cat_checked = 0
|
cat_checked = 0
|
||||||
positive_cases = 0
|
positive_cases = 0
|
||||||
for index, cat in enumerate(self.cat_filter_btns):
|
for index, cat in enumerate(self.cat_filter_btns):
|
||||||
@@ -856,15 +849,15 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
def mode_filters_ok(self, signal_name):
|
def mode_filters_ok(self, signal_name):
|
||||||
if not self.apply_remove_mode_filter_btn.isChecked():
|
if not self.apply_remove_mode_filter_btn.isChecked():
|
||||||
return True
|
return True
|
||||||
signal_mode = self.db.at[signal_name, "mode"]
|
signal_mode = self.db.at[signal_name, constants.Signal.MODE]
|
||||||
if signal_mode == Constants.UNKNOWN:
|
if signal_mode == constants.UNKNOWN:
|
||||||
if self.include_unknown_modes_btn.isChecked():
|
if self.include_unknown_modes_btn.isChecked():
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
selected_items = [item for item in self.mode_tree_widget.selectedItems()]
|
selected_items = [item for item in self.mode_tree_widget.selectedItems()]
|
||||||
selected_items_text = [i.text(0) for i in selected_items]
|
selected_items_text = [i.text(0) for i in selected_items]
|
||||||
parents = [item for item in selected_items_text if item in Constants.MODES.keys()]
|
parents = [item for item in selected_items_text if item in constants.MODES.keys()]
|
||||||
children = [item for item in selected_items_text if item not in parents]
|
children = [item for item in selected_items_text if item not in parents]
|
||||||
ok = []
|
ok = []
|
||||||
for item in selected_items:
|
for item in selected_items:
|
||||||
@@ -877,7 +870,7 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
def modulation_filters_ok(self, signal_name):
|
def modulation_filters_ok(self, signal_name):
|
||||||
if not self.apply_remove_modulation_filter_btn.isChecked():
|
if not self.apply_remove_modulation_filter_btn.isChecked():
|
||||||
return True
|
return True
|
||||||
signal_modulation = self.db.at[signal_name, "modulation"]
|
signal_modulation = self.db.at[signal_name, constants.Signal.MODULATION]
|
||||||
for item in self.modulation_list.selectedItems():
|
for item in self.modulation_list.selectedItems():
|
||||||
if item.text() == signal_modulation:
|
if item.text() == signal_modulation:
|
||||||
return True
|
return True
|
||||||
@@ -886,17 +879,12 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
def location_filters_ok(self, signal_name):
|
def location_filters_ok(self, signal_name):
|
||||||
if not self.apply_remove_location_filter_btn.isChecked():
|
if not self.apply_remove_location_filter_btn.isChecked():
|
||||||
return True
|
return True
|
||||||
signal_location = self.db.at[signal_name, "location"]
|
signal_location = self.db.at[signal_name, constants.Signal.LOCATION]
|
||||||
for item in self.locations_list.selectedItems():
|
for item in self.locations_list.selectedItems():
|
||||||
if item.text() == signal_location:
|
if item.text() == signal_location:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def filters_ok(spinbox, filter_unit, confidence, sign = 1):
|
|
||||||
band_filter = spinbox.value() * Constants.CONVERSION_FACTORS[filter_unit.currentText()]
|
|
||||||
return band_filter + sign * (confidence.value() * band_filter) // 100
|
|
||||||
|
|
||||||
@pyqtSlot(QListWidgetItem, QListWidgetItem)
|
@pyqtSlot(QListWidgetItem, QListWidgetItem)
|
||||||
def display_specs(self, item, previous_item):
|
def display_specs(self, item, previous_item):
|
||||||
self.display_spectrogram()
|
self.display_spectrogram()
|
||||||
@@ -906,33 +894,31 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
self.name_lab.setAlignment(Qt.AlignHCenter)
|
self.name_lab.setAlignment(Qt.AlignHCenter)
|
||||||
current_signal = self.db.loc[self.current_signal_name]
|
current_signal = self.db.loc[self.current_signal_name]
|
||||||
self.url_button.setEnabled(True)
|
self.url_button.setEnabled(True)
|
||||||
if not current_signal.at["url_clicked"]:
|
if not current_signal.at[constants.Signal.WIKI_CLICKED]:
|
||||||
self.url_button.setStyleSheet(f"color: {self.url_button.colors.active};")
|
self.url_button.setStyleSheet(f"color: {self.url_button.colors.active};")
|
||||||
else:
|
else:
|
||||||
self.url_button.setStyleSheet(f"color: {self.url_button.colors.clicked};")
|
self.url_button.setStyleSheet(f"color: {self.url_button.colors.clicked};")
|
||||||
category_code = current_signal.at["category_code"]
|
category_code = current_signal.at[constants.Signal.CATEGORY_CODE]
|
||||||
undef_freq = self.is_undef_freq(current_signal)
|
undef_freq = is_undef_freq(current_signal)
|
||||||
undef_band = self.is_undef_band(current_signal)
|
undef_band = is_undef_band(current_signal)
|
||||||
if not undef_freq:
|
if not undef_freq:
|
||||||
self.freq_lab.setText(self.format_numbers(
|
self.freq_lab.setText(format_numbers(current_signal.at[constants.Signal.INF_FREQ],
|
||||||
current_signal.at["inf_freq"],
|
current_signal.at[constants.Signal.SUP_FREQ])
|
||||||
current_signal.at["sup_freq"])
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.freq_lab.setText("Undefined")
|
self.freq_lab.setText("Undefined")
|
||||||
if not undef_band:
|
if not undef_band:
|
||||||
self.band_lab.setText(self.format_numbers(
|
self.band_lab.setText(format_numbers(current_signal.at[constants.Signal.INF_BAND],
|
||||||
current_signal.at["inf_band"],
|
current_signal.at[constants.Signal.SUP_BAND])
|
||||||
current_signal.at["sup_band"])
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.band_lab.setText("Undefined")
|
self.band_lab.setText("Undefined")
|
||||||
|
|
||||||
self.mode_lab.setText(current_signal.at["mode"])
|
self.mode_lab.setText(current_signal.at[constants.Signal.MODE])
|
||||||
self.modul_lab.setText(current_signal.at["modulation"])
|
self.modul_lab.setText(current_signal.at[constants.Signal.MODULATION])
|
||||||
self.loc_lab.setText(current_signal.at["location"])
|
self.loc_lab.setText(current_signal.at[constants.Signal.LOCATION])
|
||||||
self.acf_lab.setText(current_signal.at["acf"])
|
self.acf_lab.setText(current_signal.at[constants.Signal.ACF])
|
||||||
self.description_text.setText(current_signal.at["description"])
|
self.description_text.setText(current_signal.at[constants.Signal.DESCRIPTION])
|
||||||
for cat, cat_lab in zip(category_code, self.category_labels):
|
for cat, cat_lab in zip(category_code, self.category_labels):
|
||||||
if cat == '0':
|
if cat == '0':
|
||||||
cat_lab.setStyleSheet(f"color: {self.inactive_color};")
|
cat_lab.setStyleSheet(f"color: {self.inactive_color};")
|
||||||
@@ -947,64 +933,22 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
self.name_lab.setText("No Signal")
|
self.name_lab.setText("No Signal")
|
||||||
self.name_lab.setAlignment(Qt.AlignHCenter)
|
self.name_lab.setAlignment(Qt.AlignHCenter)
|
||||||
for lab in self.property_labels:
|
for lab in self.property_labels:
|
||||||
lab.setText(Constants.UNKNOWN)
|
lab.setText(constants.UNKNOWN)
|
||||||
for lab in self.category_labels:
|
for lab in self.category_labels:
|
||||||
lab.setStyleSheet(f"color: {self.inactive_color};")
|
lab.setStyleSheet(f"color: {self.inactive_color};")
|
||||||
self.set_band_range()
|
self.set_band_range()
|
||||||
self.audio_widget.set_audio_player()
|
self.audio_widget.set_audio_player()
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def is_undef_freq(current_signal):
|
|
||||||
lower_freq = current_signal.at["inf_freq"]
|
|
||||||
upper_freq = current_signal.at["sup_freq"]
|
|
||||||
return lower_freq == Constants.UNKNOWN or upper_freq == Constants.UNKNOWN
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def is_undef_band(current_signal):
|
|
||||||
lower_band = current_signal.at["inf_band"]
|
|
||||||
upper_band = current_signal.at["sup_band"]
|
|
||||||
return lower_band == Constants.UNKNOWN or upper_band == Constants.UNKNOWN
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def format_numbers(cls, lower, upper):
|
|
||||||
units = {1: 'Hz', 1000: 'kHz', 10**6: 'MHz', 10**9: 'GHz'}
|
|
||||||
lower_factor = cls.change_unit(lower)
|
|
||||||
upper_factor = cls.change_unit(upper)
|
|
||||||
pre_lower = lower
|
|
||||||
pre_upper = upper
|
|
||||||
lower = int(lower) / lower_factor
|
|
||||||
upper = int(upper) / upper_factor
|
|
||||||
if lower.is_integer():
|
|
||||||
lower = int(lower)
|
|
||||||
if upper.is_integer():
|
|
||||||
upper = int(upper)
|
|
||||||
if pre_lower != pre_upper:
|
|
||||||
return f"{lower:,} {units[lower_factor]} - {upper:,} {units[upper_factor]}"
|
|
||||||
else:
|
|
||||||
return f"{lower:,} {units[lower_factor]}"
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def change_unit(num):
|
|
||||||
digits = len(num)
|
|
||||||
if digits < 4:
|
|
||||||
return 1
|
|
||||||
elif digits < 7:
|
|
||||||
return 1000
|
|
||||||
elif digits < 10:
|
|
||||||
return 10**6
|
|
||||||
else:
|
|
||||||
return 10**9
|
|
||||||
|
|
||||||
def display_spectrogram(self):
|
def display_spectrogram(self):
|
||||||
default_pic = os.path.join(self.default_images_folder, Constants.NOT_SELECTED)
|
default_pic = os.path.join(self.default_images_folder, constants.NOT_SELECTED)
|
||||||
item = self.result_list.currentItem()
|
item = self.result_list.currentItem()
|
||||||
if item:
|
if item:
|
||||||
spectrogram_name = item.text()
|
spectrogram_name = item.text()
|
||||||
path_spectr = os.path.join(Constants.DATA_FOLDER,
|
path_spectr = os.path.join(constants.DATA_FOLDER,
|
||||||
Constants.SPECTRA_FOLDER,
|
constants.SPECTRA_FOLDER,
|
||||||
spectrogram_name + Constants.SPECTRA_EXT)
|
spectrogram_name + constants.SPECTRA_EXT)
|
||||||
if not QFileInfo(path_spectr).exists():
|
if not QFileInfo(path_spectr).exists():
|
||||||
path_spectr = os.path.join(self.default_images_folder, Constants.NOT_AVAILABLE)
|
path_spectr = os.path.join(self.default_images_folder, constants.NOT_AVAILABLE)
|
||||||
else:
|
else:
|
||||||
path_spectr = default_pic
|
path_spectr = default_pic
|
||||||
self.spectrogram.setPixmap(QPixmap(path_spectr))
|
self.spectrogram.setPixmap(QPixmap(path_spectr))
|
||||||
@@ -1015,10 +959,10 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
label.setStyleSheet(f"color: {color};")
|
label.setStyleSheet(f"color: {color};")
|
||||||
|
|
||||||
def set_band_range(self, current_signal = None):
|
def set_band_range(self, current_signal = None):
|
||||||
if current_signal is not None and not self.is_undef_freq(current_signal):
|
if current_signal is not None and not is_undef_freq(current_signal):
|
||||||
lower_freq = int(current_signal.at["inf_freq"])
|
lower_freq = int(current_signal.at[constants.Signal.INF_FREQ])
|
||||||
upper_freq = int(current_signal.at["sup_freq"])
|
upper_freq = int(current_signal.at[constants.Signal.SUP_FREQ])
|
||||||
zipped = list(zip(Constants.BANDS, self.band_labels))
|
zipped = list(zip(constants.BANDS, self.band_labels))
|
||||||
for i, w in enumerate(zipped):
|
for i, w in enumerate(zipped):
|
||||||
band, band_label = w
|
band, band_label = w
|
||||||
if lower_freq >= band.lower and lower_freq < band.upper:
|
if lower_freq >= band.lower and lower_freq < band.upper:
|
||||||
@@ -1048,8 +992,8 @@ class MyApp(QMainWindow, Ui_MainWindow):
|
|||||||
def go_to_web_page_signal(self):
|
def go_to_web_page_signal(self):
|
||||||
if self.current_signal_name:
|
if self.current_signal_name:
|
||||||
self.url_button.setStyleSheet(f"color: {self.url_button.colors.clicked}")
|
self.url_button.setStyleSheet(f"color: {self.url_button.colors.clicked}")
|
||||||
webbrowser.open(self.db.at[self.current_signal_name, "url"])
|
webbrowser.open(self.db.at[self.current_signal_name, constants.Signal.URL])
|
||||||
self.db.at[self.current_signal_name, "url_clicked"] = True
|
self.db.at[self.current_signal_name, constants.Signal.WIKI_CLICKED] = True
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
if self.download_window.isVisible():
|
if self.download_window.isVisible():
|
||||||
|
|||||||
280
main_window.ui
280
main_window.ui
@@ -174,7 +174,7 @@
|
|||||||
<enum>QTabWidget::Rounded</enum>
|
<enum>QTabWidget::Rounded</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="movable">
|
<property name="movable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@@ -1771,7 +1771,7 @@ p, li { white-space: pre-wrap; }
|
|||||||
<string notr="true"/>
|
<string notr="true"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>5</number>
|
<number>6</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="movable">
|
<property name="movable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@@ -3873,6 +3873,282 @@ Inactive</string>
|
|||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>ACF</string>
|
<string>ACF</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="include_undef_acf">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Include undefined ACFs</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_25">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_13">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>50</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>AC interval</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="acf_spinbox">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>80</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>100000000</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>50</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>ms</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_15">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>49</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_16">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string> Confidence %</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="lower_band_confidence_2">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>50</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="frame">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="buttonSymbols">
|
||||||
|
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||||
|
</property>
|
||||||
|
<property name="specialValueText">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_14">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>50</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="acf_range_lbl">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<italic>false</italic>
|
||||||
|
<bold>true</bold>
|
||||||
|
<underline>false</underline>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Selected range:
|
||||||
|
|
||||||
|
Inactive</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="DoubleTextButton" name="apply_remove_acf_filter_btn">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Apply</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="reset_acf_filters_btn">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Reset</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
2
themes/3-material_design/colors.txt
Normal file
2
themes/3-material_design/colors.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
active=#ddffdf
|
||||||
|
inactive=#949494
|
||||||
14
threads.py
14
threads.py
@@ -6,7 +6,9 @@ from shutil import rmtree
|
|||||||
import urllib3
|
import urllib3
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
from PyQt5.QtCore import QThread
|
from PyQt5.QtCore import QThread
|
||||||
from utilities import checksum_ok, Constants
|
import constants
|
||||||
|
from utilities import checksum_ok
|
||||||
|
import constants
|
||||||
|
|
||||||
class ThreadStatus(Enum):
|
class ThreadStatus(Enum):
|
||||||
OK = auto()
|
OK = auto()
|
||||||
@@ -30,8 +32,8 @@ class DownloadThread(QThread):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
db = urllib3.PoolManager().request('GET', Constants.DB_LOCATION)
|
db = urllib3.PoolManager().request('GET', constants.Database.LINK_LOC)
|
||||||
# db = urllib.request.urlopen(Constants.DB_LOCATION)
|
# db = urllib.request.urlopen(constants.Database.LINK_LOC)
|
||||||
# raise urllib.error.URLError('Test')
|
# raise urllib.error.URLError('Test')
|
||||||
except urllib3.exceptions.MaxRetryError: # No internet connection.
|
except urllib3.exceptions.MaxRetryError: # No internet connection.
|
||||||
self.__status = ThreadStatus.NO_CONNECTION_ERR
|
self.__status = ThreadStatus.NO_CONNECTION_ERR
|
||||||
@@ -40,11 +42,11 @@ class DownloadThread(QThread):
|
|||||||
self.reason = db.reason
|
self.reason = db.reason
|
||||||
self.__status = ThreadStatus.BAD_DOWNLOAD_ERR
|
self.__status = ThreadStatus.BAD_DOWNLOAD_ERR
|
||||||
return
|
return
|
||||||
if not checksum_ok(db.data, "folder"):
|
if not checksum_ok(db.data, constants.ChecksumWhat.FOLDER):
|
||||||
self.__status = ThreadStatus.BAD_DOWNLOAD_ERR
|
self.__status = ThreadStatus.BAD_DOWNLOAD_ERR
|
||||||
return
|
return
|
||||||
if os.path.exists(Constants.DATA_FOLDER):
|
if os.path.exists(constants.DATA_FOLDER):
|
||||||
rmtree(Constants.DATA_FOLDER)
|
rmtree(constants.DATA_FOLDER)
|
||||||
try:
|
try:
|
||||||
# data_folder = db.read()
|
# data_folder = db.read()
|
||||||
with ZipFile(BytesIO(db.data)) as zipped:
|
with ZipFile(BytesIO(db.data)) as zipped:
|
||||||
|
|||||||
206
utilities.py
206
utilities.py
@@ -1,159 +1,12 @@
|
|||||||
from collections import namedtuple
|
from functools import partial
|
||||||
import hashlib
|
import hashlib
|
||||||
import re
|
import re
|
||||||
from pandas import read_csv
|
from pandas import read_csv
|
||||||
|
|
||||||
from PyQt5.QtWidgets import QMessageBox
|
from PyQt5.QtWidgets import QMessageBox
|
||||||
|
|
||||||
# class _ReadOnlyProperty(object):
|
import constants
|
||||||
# def __init__(self, value):
|
|
||||||
# self.__value = value
|
|
||||||
|
|
||||||
# def __get__(self, obj, objtype):
|
|
||||||
# return self.__value
|
|
||||||
|
|
||||||
# def __set__(self, obj, value):
|
|
||||||
# return NotImplementedError("Cannot change a constant.")
|
|
||||||
|
|
||||||
# def __make_read_only(cls):
|
|
||||||
# for k, v in cls.__dict__.items():
|
|
||||||
# if not callable(getattr(cls, k)) and '__' not in k:
|
|
||||||
# setattr(cls, k, _ReadOnlyProperty(v))
|
|
||||||
# # def raise_err(self, attr, value):
|
|
||||||
# # raise NotImplementedError("Cannot add an attribute.")
|
|
||||||
# # setattr(cls, '__setattr__', raise_err)
|
|
||||||
# return cls
|
|
||||||
|
|
||||||
# @__make_read_only
|
|
||||||
class Constants(object):
|
|
||||||
class Messages(object):
|
|
||||||
NO_DB_AVAIL = "No database available.\nGo to Updates->Update database."
|
|
||||||
NO_DB = "No database"
|
|
||||||
DB_LOCATION = "https://aresvalley.com/Storage/Artemis/Database/data.zip"
|
|
||||||
REF_LOC = "https://aresvalley.com/Storage/Artemis/Database/data.zip.log"
|
|
||||||
DB_NAME = "db.csv"
|
|
||||||
DB_NAMES = ("name",
|
|
||||||
"inf_freq",
|
|
||||||
"sup_freq",
|
|
||||||
"mode",
|
|
||||||
"inf_band",
|
|
||||||
"sup_band",
|
|
||||||
"location",
|
|
||||||
"url",
|
|
||||||
"description",
|
|
||||||
"modulation",
|
|
||||||
"category_code",
|
|
||||||
"acf",)
|
|
||||||
DB_WIKI_CLICKED = "url_clicked"
|
|
||||||
DB_STRINGS = ('inf_freq',
|
|
||||||
'sup_freq',
|
|
||||||
'mode',
|
|
||||||
'inf_band',
|
|
||||||
'sup_band',
|
|
||||||
'category_code',)
|
|
||||||
DATA_FOLDER = "Data"
|
|
||||||
SPECTRA_FOLDER = "Spectra"
|
|
||||||
SPECTRA_EXT = ".png"
|
|
||||||
AUDIO_FOLDER = "Audio"
|
|
||||||
THEMES_FOLDER = "themes"
|
|
||||||
THEME_EXTENSION = ".th"
|
|
||||||
ICONS_FOLDER = "icons"
|
|
||||||
DEFAULT_THEME = "1-system"
|
|
||||||
CURRENT_THEME = ".current_theme"
|
|
||||||
THEME_COLORS = "colors.txt"
|
|
||||||
NOT_AVAILABLE = "spectrumnotavailable.png"
|
|
||||||
NOT_SELECTED = "nosignalselected.png"
|
|
||||||
SEARCH_LABEL_IMG = "search_icon.png"
|
|
||||||
VOLUME_LABEL_IMG = "volume.png"
|
|
||||||
__Band = namedtuple("Band", ["lower", "upper"])
|
|
||||||
__ELF = __Band(0, 30) # Formally it is (3, 30) Hz.
|
|
||||||
__SLF = __Band(30, 300)
|
|
||||||
__ULF = __Band(300, 3000)
|
|
||||||
__VLF = __Band(3000, 30000)
|
|
||||||
__LF = __Band(30 * 10**3, 300 * 10**3)
|
|
||||||
__MF = __Band(300 * 10 ** 3, 3000 * 10**3)
|
|
||||||
__HF = __Band(3 * 10**6, 30 * 10**6)
|
|
||||||
__VHF = __Band(30 * 10**6, 300 * 10**6)
|
|
||||||
__UHF = __Band(300 * 10**6, 3000 * 10**6)
|
|
||||||
__SHF = __Band(3 * 10**9, 30 * 10**9)
|
|
||||||
__EHF = __Band(30 * 10**9, 300 * 10**9)
|
|
||||||
BANDS = (__ELF, __SLF, __ULF, __VLF, __LF, __MF, __HF, __VHF, __UHF, __SHF, __EHF)
|
|
||||||
ACTIVE_COLOR = "#39eaff"
|
|
||||||
INACTIVE_COLOR = "#9f9f9f"
|
|
||||||
CONVERSION_FACTORS = {"Hz" : 1,
|
|
||||||
"kHz": 1000,
|
|
||||||
"MHz": 1000000,
|
|
||||||
"GHz": 1000000000}
|
|
||||||
MODES = {"FM": ("NFM", "WFM"),
|
|
||||||
"AM": (),
|
|
||||||
"CW": (),
|
|
||||||
"SK": ("FSK", "PSK", "MSK"),
|
|
||||||
"SB": ("LSB", "USB", "DSB"),
|
|
||||||
"Chirp Spread Spectrum": (),
|
|
||||||
"FHSS-TDM": (),
|
|
||||||
"RAW": (),
|
|
||||||
"SC-FDMA": (),}
|
|
||||||
APPLY = "Apply"
|
|
||||||
REMOVE = "Remove"
|
|
||||||
UNKNOWN = "N/A"
|
|
||||||
MODULATIONS = ("8VSB",
|
|
||||||
"AFSK",
|
|
||||||
"AM",
|
|
||||||
"BFSK",
|
|
||||||
"C4FM",
|
|
||||||
"CDMA",
|
|
||||||
"COFDM",
|
|
||||||
"CW",
|
|
||||||
"FFSK",
|
|
||||||
"FM",
|
|
||||||
"FMCW",
|
|
||||||
"FMOP",
|
|
||||||
"FSK",
|
|
||||||
"GFSK",
|
|
||||||
"GMSK",
|
|
||||||
"IFK",
|
|
||||||
"MFSK",
|
|
||||||
"MSK",
|
|
||||||
"OFDM",
|
|
||||||
"OOK",
|
|
||||||
"PAM",
|
|
||||||
"PPM",
|
|
||||||
"PSK",
|
|
||||||
"QAM",
|
|
||||||
"TDMA",)
|
|
||||||
LOCATIONS = (UNKNOWN,
|
|
||||||
"Australia",
|
|
||||||
"Canada",
|
|
||||||
"Central Europe",
|
|
||||||
"China",
|
|
||||||
"Cyprus",
|
|
||||||
"Eastern Europe",
|
|
||||||
"Europe",
|
|
||||||
"Europe, japan and Asia",
|
|
||||||
"Exmouth, Australia",
|
|
||||||
"Finland",
|
|
||||||
"France",
|
|
||||||
"Germany",
|
|
||||||
"Home Base Mobile , AL",
|
|
||||||
"Hungary",
|
|
||||||
"Iran",
|
|
||||||
"Israel",
|
|
||||||
"Japan",
|
|
||||||
"LaMour, North Dakota",
|
|
||||||
"Lualualei, Hawaii",
|
|
||||||
"North America",
|
|
||||||
"North Korea",
|
|
||||||
"Poland",
|
|
||||||
"Romania",
|
|
||||||
"Ruda, Sweden",
|
|
||||||
"UK",
|
|
||||||
"United Kingdom",
|
|
||||||
"United States",
|
|
||||||
"Varberg, Sweden",
|
|
||||||
"World Wide",
|
|
||||||
"Worldwide",)
|
|
||||||
|
|
||||||
# Constants = __Constants()
|
|
||||||
|
|
||||||
def reset_apply_remove_btn(button):
|
def reset_apply_remove_btn(button):
|
||||||
if button.isChecked():
|
if button.isChecked():
|
||||||
@@ -165,23 +18,70 @@ def throwable_message(cls, title, text, connection = None):
|
|||||||
msg.setWindowTitle(title)
|
msg.setWindowTitle(title)
|
||||||
msg.setText(text)
|
msg.setText(text)
|
||||||
if connection:
|
if connection:
|
||||||
msg.setText(text).finished.connect(connection)
|
msg.finished.connect(connection)
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
def checksum_ok(data, what):
|
def checksum_ok(data, what):
|
||||||
code = hashlib.sha256()
|
code = hashlib.sha256()
|
||||||
code.update(data)
|
code.update(data)
|
||||||
if what == "folder":
|
if what == constants.ChecksumWhat.FOLDER:
|
||||||
n = 0
|
n = 0
|
||||||
elif what == "db":
|
elif what == constants.ChecksumWhat.DB:
|
||||||
n = 1
|
n = 1
|
||||||
else:
|
else:
|
||||||
raise ValueError("Wrong entry name.")
|
raise ValueError("Wrong entry name.")
|
||||||
try:
|
try:
|
||||||
reference = read_csv(Constants.REF_LOC, delimiter = '*').iat[-1, n]
|
reference = read_csv(constants.Database.LINK_REF,
|
||||||
|
delimiter = constants.Database.DELIMITER).iat[-1, n]
|
||||||
except HTTPError:
|
except HTTPError:
|
||||||
return False
|
return False
|
||||||
return code.hexdigest() == reference
|
return code.hexdigest() == reference
|
||||||
|
|
||||||
def is_valid_html_color(color):
|
def is_valid_html_color(color):
|
||||||
return bool(re.match("#([a-zA-Z0-9]){6}", color))
|
return bool(re.match("#([a-zA-Z0-9]){6}", color))
|
||||||
|
|
||||||
|
def connect_to(objects_to_connect, fun_to_connect, fun_args):
|
||||||
|
for signal in objects_to_connect:
|
||||||
|
signal.connect(partial(fun_to_connect, *fun_args))
|
||||||
|
|
||||||
|
def filters_ok(spinbox, filter_unit, confidence, sign = 1):
|
||||||
|
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):
|
||||||
|
lower_freq = current_signal.at[constants.Signal.INF_FREQ]
|
||||||
|
upper_freq = current_signal.at[constants.Signal.SUP_FREQ]
|
||||||
|
return lower_freq == constants.UNKNOWN or upper_freq == constants.UNKNOWN
|
||||||
|
|
||||||
|
def is_undef_band(current_signal):
|
||||||
|
lower_band = current_signal.at[constants.Signal.INF_BAND]
|
||||||
|
upper_band = current_signal.at[constants.Signal.SUP_BAND]
|
||||||
|
return lower_band == constants.UNKNOWN or upper_band == constants.UNKNOWN
|
||||||
|
|
||||||
|
def change_unit(num):
|
||||||
|
digits = len(num)
|
||||||
|
if digits < 4:
|
||||||
|
return 1
|
||||||
|
elif digits < 7:
|
||||||
|
return 1000
|
||||||
|
elif digits < 10:
|
||||||
|
return 10**6
|
||||||
|
else:
|
||||||
|
return 10**9
|
||||||
|
|
||||||
|
def format_numbers(lower, upper):
|
||||||
|
units = {1: 'Hz', 1000: 'kHz', 10**6: 'MHz', 10**9: 'GHz'}
|
||||||
|
lower_factor = change_unit(lower)
|
||||||
|
upper_factor = change_unit(upper)
|
||||||
|
pre_lower = lower
|
||||||
|
pre_upper = upper
|
||||||
|
lower = int(lower) / lower_factor
|
||||||
|
upper = int(upper) / upper_factor
|
||||||
|
if lower.is_integer():
|
||||||
|
lower = int(lower)
|
||||||
|
if upper.is_integer():
|
||||||
|
upper = int(upper)
|
||||||
|
if pre_lower != pre_upper:
|
||||||
|
return f"{lower:,} {units[lower_factor]} - {upper:,} {units[upper_factor]}"
|
||||||
|
else:
|
||||||
|
return f"{lower:,} {units[lower_factor]}"
|
||||||
Reference in New Issue
Block a user