8 Commits

Author SHA1 Message Date
Marco Dalla Tiezza
36648e08cc Updated message on preference window, bump Artemis version to 4.0.5 2024-06-15 12:09:14 +02:00
Marco Dalla Tiezza
d61caa1ada Removed unused imports, added date parser for db info data 2024-06-15 12:01:33 +02:00
Marco Dalla Tiezza
6fdd36b548 Code optimized: removed an additional db loading 2024-06-15 11:44:01 +02:00
Marco Dalla Tiezza
6213e8b1ca Added creation date and version of the db on db manager window 2024-06-15 00:55:05 +02:00
Marco Dalla Tiezza
d0bfbe40d7 New logic for local sigid search 2024-06-15 00:40:00 +02:00
Marco Dalla Tiezza
ebda950c87 Updated docs 2024-06-14 21:33:42 +02:00
Marco Dalla Tiezza
c803a72489 Updated changelog and resources (after merge) 2024-06-14 01:18:48 +02:00
Marco Dalla Tiezza
70758ea8bd Merge pull request #51 from AresValley/revised-networking
Revised network manager, update manager and downloader
2024-06-13 23:08:42 +00:00
16 changed files with 7526 additions and 79 deletions

View File

@@ -5,14 +5,25 @@
## [Unreleased] ## [Unreleased]
## [4.0.5] - 2024-06-15
### Added ### Added
- Possibility to navigate Artemis just with the keyboard [#50](https://github.com/AresValley/Artemis/issues/50) - Possibility to navigate Artemis just with the keyboard [#50](https://github.com/AresValley/Artemis/issues/50)
- **Windows:** automatic updates have been implemented. When a software update is available, Artemis will download the new version and install the updates automatically
- Multiple sigID databases can be conserved. In the case of autoload, the latest local version will be loaded
- Added creation date and DB version in DB manager window
### Changed ### Changed
- Improved readability of labels for filter ranges for frequency, bandwidth, and ACF - Improved readability of labels for filter ranges for frequency, bandwidth, and ACF
- Improved Update manager and Downloader functionalities
- OS dependent temporary folders are now used for database download and artemis updates
- The logic for searching the last sigID database has changed, now the discriminant is no longer the folder name but is reported as a signature in the database itself (-1 in the editable field, see documentation)
- Old sigID databases are not deleted anymore when a new version is downloaded. This is to avoid removing databases with user changes or additions
### Fixed ### Fixed
- Added a database load check to avoid (non critical) exceptions when applying filters without having loaded a database. - Added a database load check to avoid (non critical) exceptions when applying filters without having loaded a database.
- Fixed a potential issue involing the forcibly closure of downloader window but the downloader instance keeps running
- With the new logic in the latest sigID database search, manually imported sigID databases are officially recognized as proper ones
## [4.0.3] - 2024-06-10 ## [4.0.3] - 2024-06-10
@@ -109,7 +120,8 @@ First release.
<!-- Links definitions --> <!-- Links definitions -->
[Unreleased]: https://github.com/AresValley/Artemis/compare/v4.0.3...HEAD [Unreleased]: https://github.com/AresValley/Artemis/compare/v4.0.5...HEAD
[4.0.5]: https://github.com/AresValley/Artemis/compare/v4.0.3...v4.0.5
[4.0.3]: https://github.com/AresValley/Artemis/compare/v4.0.1...v4.0.3 [4.0.3]: https://github.com/AresValley/Artemis/compare/v4.0.1...v4.0.3
[4.0.1]: https://github.com/AresValley/Artemis/compare/v3.2.4...v4.0.1 [4.0.1]: https://github.com/AresValley/Artemis/compare/v3.2.4...v4.0.1
[3.2.4]: https://github.com/AresValley/Artemis/compare/v3.2.1...v3.2.4 [3.2.4]: https://github.com/AresValley/Artemis/compare/v3.2.1...v3.2.4

File diff suppressed because it is too large Load Diff

View File

@@ -345,10 +345,13 @@ class UIArtemis(QObject):
def autoload_db(self): def autoload_db(self):
sig_id_path = DATA_DIR / 'SigID' / Constants.SQL_NAME """ This will autoload the latest local sigID DB, if present
according to the user settings
"""
sig_id_db = self.dbmanager.get_latest_local_sigid_db()
autoload = CONFIGURE_QT.value("Database", "autoload", 0) autoload = CONFIGURE_QT.value("Database", "autoload", 0)
if sig_id_path.exists() and int(autoload): if sig_id_db is not None and int(autoload):
self.load_db('SigID') self.load_db(sig_id_db.db_dir_name)
def dialog_popup(self, message_type, title, message): def dialog_popup(self, message_type, title, message):

View File

@@ -6,7 +6,6 @@ from PySide6.QtCore import QObject, Signal, Slot
from artemis.utils.path_utils import DATA_DIR from artemis.utils.path_utils import DATA_DIR
from artemis.utils.generic_utils import * from artemis.utils.generic_utils import *
from artemis.utils.sql_utils import ArtemisDatabase from artemis.utils.sql_utils import ArtemisDatabase
from artemis.utils.constants import Constants
from artemis.utils.sys_utils import delete_dir from artemis.utils.sys_utils import delete_dir
@@ -49,8 +48,24 @@ class UIdbmanager(QObject):
def load_local_db_list(self): def load_local_db_list(self):
""" Scan for all the valid DBs in the data folder and show them on the list """ Scan for all the valid DBs in the data folder and show them on the list
""" """
db_param = []
valid_db_list = self.scan_db_dir() valid_db_list = self.scan_db_dir()
self.populate_db_list.emit(valid_db_list)
for db in valid_db_list:
db_param.append(
{
'name': db.name,
'version': db.version,
'date': parse_date(db.date),
'db_dir_name': db.db_dir_name,
'documents_n': db.stats['documents'],
'signals_n': db.stats['signals'],
'images_n': db.stats['images'],
'audio_n': db.stats['audio']
}
)
self.populate_db_list.emit(db_param)
def load_db(self, db_dir_name): def load_db(self, db_dir_name):
@@ -85,43 +100,32 @@ class UIdbmanager(QObject):
def scan_db_dir(self): def scan_db_dir(self):
""" Scans the data directory for valid databases and """ Scans the data directory for valid databases and
return a dictionary containing only the valid ones with a summary return a dictionary containing only the valid ones.
Returns a list of objects (dbs)
""" """
valid_db_list = [] valid_db_list = []
db_dirs = next(os.walk(DATA_DIR))[1] db_dirs = next(os.walk(DATA_DIR))[1]
for db_dir_name in db_dirs: for db_dir_name in db_dirs:
if self._valid_db(db_dir_name): try:
database = ArtemisDatabase(db_dir_name) database = ArtemisDatabase(db_dir_name)
database.load() database.load()
valid_db_list.append( valid_db_list.append(database)
{ except:
'name': database.name, continue
'db_dir_name': database.db_dir_name,
'documents_n': database.stats['documents'],
'signals_n': database.stats['signals'],
'images_n': database.stats['images'],
'audio_n': database.stats['audio']
}
)
return valid_db_list return valid_db_list
def _valid_db(self, db_dir_name): def get_latest_local_sigid_db(self):
""" Checks if db_dir_name is a valid db dir containing a `data.sqlite` file. """ Return the newest valid local sigID database.
Db must be valid as well and should be properly initialized and loaded with Returns None if no valid sigID database is found.
no errors.
Args:
db_dir_name (str): name of the db folder
""" """
if os.path.exists(DATA_DIR / db_dir_name / Constants.SQL_NAME): valid_dbs = self._parent.dbmanager.scan_db_dir()
try: sig_id_dbs = [db for db in valid_dbs if db.editable == -1]
database = ArtemisDatabase(db_dir_name)
database.load() if len(sig_id_dbs) != 0:
return True sig_id_latest = max(sig_id_dbs, key=lambda x: x.version)
except: return sig_id_latest
return False # Invalid or corrupted DB
else: else:
return False # The dir is not containing a data.sqlite file return None

View File

@@ -10,7 +10,7 @@ class Constants():
APPLICATION_NAME = 'Artemis' APPLICATION_NAME = 'Artemis'
ORGANIZATION_NAME = 'AresValley' ORGANIZATION_NAME = 'AresValley'
ORGANIZATION_DOMAIN = 'aresvalley.com' ORGANIZATION_DOMAIN = 'aresvalley.com'
APPLICATION_VERSION = '4.0.3' APPLICATION_VERSION = '4.0.5'
SQL_NAME = 'data.sqlite' SQL_NAME = 'data.sqlite'

View File

@@ -1,3 +1,5 @@
from datetime import datetime
from artemis.utils.constants import Query from artemis.utils.constants import Query
@@ -75,3 +77,17 @@ def generate_filter_query(filer_status):
)) ))
return ' INTERSECT '.join(query) return ' INTERSECT '.join(query)
def parse_date(date_str):
""" Parses a date string in "%Y-%m-%d %H:%M:%S.%f" format and returns
the date in "YYYY-MM-DD" format. If parsing fails, returns the original string.
Args:
date_str (str): The date string to parse.
"""
try:
form_date = datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S.%f")
return str(form_date.date())
except ValueError:
return date_str

View File

@@ -7,8 +7,8 @@ from datetime import datetime
from contextlib import closing from contextlib import closing
from artemis.utils.constants import Query, Constants from artemis.utils.constants import Query, Constants
from artemis.utils.path_utils import DATA_DIR
from artemis.utils.generic_utils import format_frequency from artemis.utils.generic_utils import format_frequency
from artemis.utils.path_utils import DATA_DIR
class Database(): class Database():
@@ -141,7 +141,7 @@ class ArtemisDatabase(Database):
""" Create new db in the data folder. """ Create new db in the data folder.
The name of folder containing the new db has a unique id as name (db_dir_name). The name of folder containing the new db has a unique id as name (db_dir_name).
""" """
meta = [name, datetime.now(), 0, 0] meta = [name, datetime.now(), 1, 1]
os.makedirs(self.db_dir) os.makedirs(self.db_dir)
os.makedirs(self.media_dir) os.makedirs(self.media_dir)

View File

@@ -1,11 +1,10 @@
import os import uuid
import requests import requests
from packaging.version import Version from packaging.version import Version
from artemis.utils.constants import Constants, Messages from artemis.utils.constants import Constants, Messages
from artemis.utils.sql_utils import ArtemisDatabase from artemis.utils.sys_utils import is_windows, is_linux, is_macos, delete_file, match_hash, unpack_tar, open_file
from artemis.utils.sys_utils import is_windows, is_linux, is_macos, delete_file, delete_dir, match_hash, unpack_tar, open_file
from artemis.utils.path_utils import DATA_DIR, TMP_DIR from artemis.utils.path_utils import DATA_DIR, TMP_DIR
@@ -15,7 +14,6 @@ class UpdateManager:
def __init__(self, parent): def __init__(self, parent):
self._parent = parent self._parent = parent
self.sigid_db_path = DATA_DIR / 'SigID' / Constants.SQL_NAME
self.db_update = None self.db_update = None
self.art_update = None self.art_update = None
@@ -45,7 +43,7 @@ class UpdateManager:
""" """
latest_json = self.fetch_remote_json(Constants.LATEST_VERSION_URL, show_popup) latest_json = self.fetch_remote_json(Constants.LATEST_VERSION_URL, show_popup)
if latest_json: if latest_json:
local_db = self._load_local_db() local_db = self._parent.dbmanager.get_latest_local_sigid_db()
remote_db = latest_json['sigID_DB'] remote_db = latest_json['sigID_DB']
self.remote_db_version = remote_db['version'] self.remote_db_version = remote_db['version']
@@ -104,16 +102,6 @@ class UpdateManager:
return None return None
def _load_local_db(self):
""" Loads the local database if exists
"""
if os.path.exists(self.sigid_db_path):
local_db = ArtemisDatabase('SigID')
local_db.load()
return local_db
return None
def download_db(self): def download_db(self):
""" Open the downloader and download the sigID database in the """ Open the downloader and download the sigID database in the
TMP_DIR folder. After a succesfull download the callback function TMP_DIR folder. After a succesfull download the callback function
@@ -133,9 +121,9 @@ class UpdateManager:
""" """
latest_db_tar_path = TMP_DIR / self.remote_db_file_name latest_db_tar_path = TMP_DIR / self.remote_db_file_name
if match_hash(latest_db_tar_path, self.remote_db_hash): if match_hash(latest_db_tar_path, self.remote_db_hash):
delete_dir(DATA_DIR / 'SigID') db_dir_name = str(uuid.uuid4())
unpack_tar(latest_db_tar_path, DATA_DIR / 'SigID') unpack_tar(latest_db_tar_path, DATA_DIR / db_dir_name)
self._parent.load_db('SigID') self._parent.load_db(db_dir_name)
self._show_popup_db_download_complete() self._show_popup_db_download_complete()
else: else:
self._show_popup_db_hash_failed() self._show_popup_db_hash_failed()

View File

@@ -25,8 +25,8 @@ python -m nuitka app.py `
--force-stdout-spec="{TEMP}\artemis.out.log" ` --force-stdout-spec="{TEMP}\artemis.out.log" `
--windows-company-name=Aresvalley.com ` --windows-company-name=Aresvalley.com `
--windows-product-name=Artemis ` --windows-product-name=Artemis `
--windows-file-version=4.0.3 ` --windows-file-version=4.0.5 `
--windows-product-version=4.0.3 ` --windows-product-version=4.0.5 `
--windows-file-description=Artemis ` --windows-file-description=Artemis `
--windows-icon-from-ico=images\artemis_icon.ico --windows-icon-from-ico=images\artemis_icon.ico

View File

@@ -1,5 +1,5 @@
#define MyAppName "Artemis" #define MyAppName "Artemis"
#define MyAppVersion "4.0.3" #define MyAppVersion "4.0.5"
#define MyAppPublisher "AresValley" #define MyAppPublisher "AresValley"
#define MyAppURL "https://www.aresvalley.com/" #define MyAppURL "https://www.aresvalley.com/"
#define MyAppExeName "artemis.exe" #define MyAppExeName "artemis.exe"

View File

@@ -23,6 +23,6 @@ python -m nuitka app.py \
--macos-app-name=Artemis \ --macos-app-name=Artemis \
--macos-app-mode=gui \ --macos-app-mode=gui \
--macos-sign-identity=ad-hoc \ --macos-sign-identity=ad-hoc \
--macos-app-version=4.0.3 --macos-app-version=4.0.5
echo "Building Linux target finished." echo "Building Linux target finished."

View File

@@ -2,7 +2,7 @@
"sigID_DB": { "sigID_DB": {
"version": 61, "version": 61,
"url": "https://github.com/AresValley/Artemis-DB/releases/download/v61/v61.tar", "url": "https://github.com/AresValley/Artemis-DB/releases/download/v61/v61.tar",
"sha256_hash": "c65d2ab65e9420cd7789190c100abef2f1575ea15489776c2d97b5b09cdc8410", "sha256_hash": "da4d0f56924940f90b86349bf7a22a478bcf08e969d8de2bcb34e2939e74c885",
"total_bytes": 244449280 "total_bytes": 244449280
}, },
"windows": { "windows": {

View File

@@ -5,21 +5,58 @@
## 1. Main Menu ## 1. Main Menu
### File ### File
* **New Database:** Create a new database.
* **Load Database:** Open the Database Manager windows in order to open, rename, or delete a database. * **New Database**
* **Import Database:** Import an Artemis database with a standard .tar format.
* **Export Database:** Export the loaded database with a standard .tar format. Create a new database.
* **Edit Tags:** Open the tags editor window. From here, you can add, rename, or delete tags. The tags can be added to a signal from the [tags menu](#4-tags)
* **Open Database Folder:** Shows the folder of the currently loaded database in the explorer. * **Load Database**
* **Preferences:** Open the program settings window.
* **Exit:** This will close the application. Open the Database Manager windows in order to open, rename, or delete a database.
* **Import Database**
Import an Artemis database with a standard .tar format.
!!! tip "Offline Importing of SigID Database"
Sometimes it may happen that a computer does not have network access and unfortunately Artemis cannot download the SigID database. To solve this you can:
1. Download the .tar database [:material-download: HERE](https://github.com/AresValley/Artemis-DB/releases) from a PC with an internet access
2. Import the downloaded .tar on the target PC (without internet access) using the **Import Database** function
* **Export Database**
Export the loaded database with a standard .tar format.
* **Edit Tags**
Open the tags editor window. From here, you can add, rename, or delete tags. The tags can be added to a signal from the [tags menu](#4-tags)
* **Open Database Folder**
Shows the folder of the currently loaded database in the explorer.
* **Preferences**
Open the program settings window.
* **Exit**
This will close the application.
### Signal ### Signal
* **New:** Add a new signal to the database. * **New**
* **Edit:** Edit the current/selected signal from the loaded database.
Add a new signal to the database.
* **Edit**
Edit the current/selected signal from the loaded database.
### Space Weather ### Space Weather
* **Check Report:** Open the main [Space Weather window](space_weather/current.md) and retrieve all the live data from Poseidon Crawler.
* **Check Report**
Open the main [Space Weather window](space_weather/current.md) and retrieve all the live data from Poseidon Crawler.
## 2. Signal List ## 2. Signal List
This is the signal list where all the database entries are shown. When a signal is selected, it will load on the right panel. This is the signal list where all the database entries are shown. When a signal is selected, it will load on the right panel.
@@ -31,9 +68,18 @@ On top of the list, there is a field for filtering signals by name or any keywor
Here you can swithc between the main **signal** window and the **filter** page. Here you can swithc between the main **signal** window and the **filter** page.
## 4. Tags ## 4. Tags
* **Associate Tag:** Custom tags can be associated to the selected signal with the :octicons-plus-circle-16: icon
* **Remove Tag:** In order to remove a tag, just click on its badge. * **Associate Tag**
* **Add/Rename Tag:** To add a new tag open the [Tags Editor](#1-main-menu) in the main menu.
Custom tags can be associated to the selected signal with the :octicons-plus-circle-16: icon
* **Remove Tag**
In order to remove a tag, just click on its badge.
* **Add/Rename Tag**
To add a new tag open the [Tags Editor](#1-main-menu) in the main menu.
## 5. Add Parameter ## 5. Add Parameter
Click on the labels to add the corresponding parameter to the signal (e.g. click on **Frequency** to add a new frequency). Click on the labels to add the corresponding parameter to the signal (e.g. click on **Frequency** to add a new frequency).

View File

@@ -21,8 +21,6 @@ A simple integer to denote the database version.
This field should serve as a writing protection on the database. This field should serve as a writing protection on the database.
* **-1**: reserved to sigID database. This is the primary way to distinguish a valid sigID database
* **0**: read-only database * **0**: read-only database
* **1**: database can be edited with no restrictions * **1**: database can be edited with no restrictions
!!! example "Experimental"
This feature is experimental and not yet implemented.

View File

@@ -33,6 +33,8 @@ Window {
if (selected_db !== undefined) { if (selected_db !== undefined) {
lockMenu(false) lockMenu(false)
titleLabel.text = myModel.get(listView.currentIndex).name titleLabel.text = myModel.get(listView.currentIndex).name
versionLabel.text = 'VERSION ' + myModel.get(listView.currentIndex).version
dateLabel.text = myModel.get(listView.currentIndex).date
totDocsLabel.text = myModel.get(listView.currentIndex).documents_n totDocsLabel.text = myModel.get(listView.currentIndex).documents_n
totSignalsLabel.text = myModel.get(listView.currentIndex).signals_n totSignalsLabel.text = myModel.get(listView.currentIndex).signals_n
totImagesLabel.text = myModel.get(listView.currentIndex).images_n totImagesLabel.text = myModel.get(listView.currentIndex).images_n
@@ -44,6 +46,8 @@ Window {
function clearAll() { function clearAll() {
titleLabel.text = 'N/A' titleLabel.text = 'N/A'
versionLabel.text = ''
dateLabel.text = ''
totDocsLabel.text = '' totDocsLabel.text = ''
totSignalsLabel.text = '' totSignalsLabel.text = ''
totImagesLabel.text = '' totImagesLabel.text = ''
@@ -175,11 +179,16 @@ Window {
Label { Label {
id: titleLabel id: titleLabel
Layout.bottomMargin: 20
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
font.pointSize: 15 font.pointSize: 15
font.bold: true font.bold: true
} }
Label {
id: versionLabel
Layout.bottomMargin: 20
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
font.pointSize: 9
}
GridLayout { GridLayout {
columnSpacing: 25 columnSpacing: 25
columns: 2 columns: 2
@@ -230,7 +239,20 @@ Window {
id: totAudioLabel id: totAudioLabel
text: qsTr("0") text: qsTr("0")
font.pointSize: 12 font.pointSize: 12
} }
Label {
Layout.topMargin: 20
text: qsTr("DB Created:")
font.pointSize: 12
}
Label {
id: dateLabel
Layout.topMargin: 20
text: qsTr("")
font.pointSize: 12
}
} }
Item { Item {

View File

@@ -146,7 +146,7 @@ Window {
Layout.fillWidth: true Layout.fillWidth: true
Label { Label {
text: "Auto-load SigID Database on Startup" text: "Auto-load SigID database on startup (latest version)"
font.pixelSize: 12 font.pixelSize: 12
clip: true clip: true
Layout.fillWidth: true Layout.fillWidth: true