10 Commits

Author SHA1 Message Date
Marco Dalla Tiezza
1b48405c14 Rolling out DB v61 2024-06-05 22:20:43 +02:00
Marco Dalla Tiezza
c8fcb2c3e0 Added project webpage in help section 2024-06-05 21:03:06 +02:00
Marco Dalla Tiezza
ab8403c16e Corrected few docs typo 2024-06-05 00:05:00 +02:00
Marco Dalla Tiezza
7929c23ac5 Fixed a bug introduced in 10607c88ea 2024-06-04 22:15:44 +02:00
Marco Dalla Tiezza
707cc001cf Updated docs about new text search behaviour 2024-06-04 21:57:56 +02:00
Marco Dalla Tiezza
4594237c09 Added volume slider and mute bbutton to audio player, closed #45 2024-06-04 21:43:57 +02:00
Marco Dalla Tiezza
10607c88ea Searches in the name field has been extended to the description as well (close #44) 2024-06-04 19:51:21 +02:00
Marco Dalla Tiezza
f61527ed70 Locked audio player upon signal deletion 2024-06-04 19:30:15 +02:00
Marco Dalla Tiezza
4e7ebcc2f5 Read-only ops are separated in different standard and OS dependent folders from read-write ones (fixed #43), bump Nuitka 2.3 2024-06-04 19:25:12 +02:00
Marco Dalla Tiezza
16e2668fe9 Forced std error and std output in building script for Windows for logging purposes 2024-06-02 00:57:32 +02:00
32 changed files with 1152 additions and 981 deletions

View File

@@ -12,13 +12,18 @@
- Databases can be exported/imported for easy sharing
- Possibility to store and view all type of documents related to a signal entry
- Filtration process is now much more efficient due to usage of SQL queries
- D-Region Absorption Predictions (DRAP) and Aurora OVATION model are now present in the Space Weather window
### Changed
- Updated GUI libray from PyQt5 to PySide6. Artemis 4 now relies on the QtQuick framework.
- Undefined value for frequency and bandwidth is now deprecated.
- SigID standard database is now hosted on GitHub (the server is much faster) along with the website parser
- Undefined value for frequency and bandwidth is now deprecated
- Drastically reduced the number of third party libraries
- The signals filtering page has been simplified to be more immediate and user friendly
- Space weather page now relies on Poseidon daemon (hosted on aresvalley.com)
- Space weather page has been greatly improved and now relies on Poseidon daemon (hosted on aresvalley.com)
### Fixed
- Artemis can be execunted inside standard pretected folder (such as Program Files) without using elevated privileges
## [3.2.4] - 2022-09-30
### Fixed

View File

@@ -12,6 +12,7 @@
<file>images/icons/player_play.svg</file>
<file>images/icons/player_stop.svg</file>
<file>images/icons/player_loop.svg</file>
<file>images/icons/player_mute.svg</file>
<file>images/icons/save.svg</file>
<file>images/icons/delete.svg</file>
<file>images/icons/add.svg</file>

File diff suppressed because it is too large Load Diff

View File

@@ -4,9 +4,9 @@ from PySide6.QtQml import QQmlApplicationEngine
from PySide6.QtCore import QObject, Slot, Signal
from artemis.utils.constants import Constants, Messages
from artemis.utils.sys_utils import open_directory, pack_db, unpack_db
from artemis.utils.sys_utils import open_directory, make_tar, unpack_tar
from artemis.utils.sql_utils import ArtemisDatabase, ArtemisSignal
from artemis.utils.path_utils import check_data_dir
from artemis.utils.path_utils import DATA_DIR
from artemis.utils.network_utils import NetworkManager
from artemis.utils.generic_utils import generate_filter_query
from artemis.utils.path_utils import normalize_dialog_path
@@ -69,8 +69,6 @@ class UIArtemis(QObject):
self.network_manager = NetworkManager(self)
check_data_dir()
def _connect(self):
# QML > Python connections
@@ -277,7 +275,7 @@ class UIArtemis(QObject):
"""
try:
dest_path = normalize_dialog_path(save_path)
pack_db(dest_path, self.loaded_db.db_dir)
make_tar(dest_path, self.loaded_db.db_dir)
self.dialog_popup(
Messages.DIALOG_TYPE_INFO,
Messages.GENERIC_SUCCESS,
@@ -300,7 +298,8 @@ class UIArtemis(QObject):
"""
try:
origin_path = normalize_dialog_path(tar_path)
unpack_db(origin_path, str(uuid.uuid4()))
save_path = DATA_DIR / str(uuid.uuid4())
unpack_tar(origin_path, save_path)
self.dialog_popup(
Messages.DIALOG_TYPE_INFO,
Messages.GENERIC_SUCCESS,

View File

@@ -1,10 +1,13 @@
import os
from PySide6.QtQml import QQmlApplicationEngine
from PySide6.QtCore import QObject, Signal, Slot
from artemis.utils.path_utils import *
from artemis.utils.path_utils import DATA_DIR
from artemis.utils.generic_utils import *
from artemis.utils.sql_utils import ArtemisDatabase
from artemis.utils.constants import Constants
from artemis.utils.sys_utils import delete_dir
class UIdbmanager(QObject):
@@ -67,7 +70,7 @@ class UIdbmanager(QObject):
self._parent.lock_menu.emit(True)
self._parent.clear_list.emit()
self._parent.clear_signal_page.emit()
delete_db_dir(db_dir_name)
delete_dir(DATA_DIR / db_dir_name)
self.load_local_db_list()
@@ -85,10 +88,10 @@ class UIdbmanager(QObject):
return a dictionary containing only the valid ones with a summary
"""
valid_db_list = []
db_dirs = next(os.walk(Constants.DB_DIR))[1]
db_dirs = next(os.walk(DATA_DIR))[1]
for db_dir_name in db_dirs:
if valid_db(db_dir_name):
if self._valid_db(db_dir_name):
database = ArtemisDatabase(db_dir_name)
database.load()
valid_db_list.append(
@@ -103,3 +106,22 @@ class UIdbmanager(QObject):
)
return valid_db_list
def _valid_db(self, db_dir_name):
""" Checks if db_dir_name is a valid db dir containing a `data.sqlite` file.
Db must be valid as well and should be properly initialized and loaded with
no errors.
Args:
db_dir_name (str): name of the db folder
"""
if os.path.exists(DATA_DIR / db_dir_name / Constants.SQL_NAME):
try:
database = ArtemisDatabase(db_dir_name)
database.load()
return True
except:
return False # Invalid or corrupted DB
else:
return False # The dir is not containing a data.sqlite file

View File

@@ -3,9 +3,9 @@ from PySide6.QtCore import QObject, Slot, Signal, QUrl, QSaveFile, QDir, QIODevi
from PySide6.QtNetwork import QNetworkReply, QNetworkRequest, QNetworkAccessManager
from artemis.utils.config_utils import *
from artemis.utils.sys_utils import delete_file, match_hash, unpack_db
from artemis.utils.sys_utils import delete_file, delete_dir, match_hash, unpack_tar
from artemis.utils.constants import Messages
from artemis.utils.sys_utils import delete_db_dir
from artemis.utils.path_utils import DATA_DIR
class UIDownloader(QObject):
@@ -42,7 +42,7 @@ class UIDownloader(QObject):
the attributes of the UpdatesController class
"""
url_file = QUrl(self._parent.network_manager.remote_db_url)
dest_path = QDir(Constants.DB_DIR)
dest_path = QDir(DATA_DIR)
self.dest_file = dest_path.filePath(url_file.fileName())
self.file = QSaveFile(self.dest_file)
@@ -97,8 +97,8 @@ class UIDownloader(QObject):
if match_hash(self.dest_file, self._parent.network_manager.remote_db_hash):
self._label_progress.setProperty("text", "Unpacking archive...")
delete_db_dir('SigID')
unpack_db(self.dest_file, 'SigID')
delete_dir(DATA_DIR / 'SigID')
unpack_tar(self.dest_file, DATA_DIR / 'SigID')
delete_file(self.dest_file)
self._parent.load_db('SigID')
self.close_ui.emit()

View File

@@ -4,6 +4,7 @@ from PySide6.QtCore import QObject, Signal, Slot
from artemis.utils.path_utils import *
from artemis.utils.generic_utils import *
from artemis.utils.sql_utils import ArtemisSignal
from artemis.utils.sys_utils import delete_file
class UIsignaleditor(QObject):
@@ -104,6 +105,7 @@ class UIsignaleditor(QObject):
"""
if param_type == 'Signal':
self._parent.loaded_sig.delete_signal()
self._parent.lock_audio_player.emit()
for doc in self._parent.loaded_sig.documents:
doc_file_name = '{}.{}'.format(str(doc[0]), doc[1])
doc_file_path = self._parent.loaded_db.media_dir / doc_file_name

View File

@@ -1,5 +1,7 @@
from configparser import ConfigParser
from artemis.utils.constants import Constants
from artemis.utils.path_utils import PREFERENCES_DIR, BASE_DIR
from artemis.utils.sys_utils import copy_file
class Config(ConfigParser):
@@ -29,4 +31,11 @@ class Config(ConfigParser):
with open(self._config_file_path, 'w') as f:
self.write(f, space_around_delimiters=self._space_around_delimiters)
CONFIGURE_QT = Config((Constants.PREFERENCES_DIR / 'qtquickcontrols2.conf').resolve().as_posix())
if not (PREFERENCES_DIR / 'qtquickcontrols2.conf').exists():
copy_file(
BASE_DIR / 'config' / 'qtquickcontrols2.conf',
PREFERENCES_DIR / 'qtquickcontrols2.conf'
)
CONFIGURE_QT = Config((PREFERENCES_DIR / 'qtquickcontrols2.conf').resolve().as_posix())

View File

@@ -1,9 +1,7 @@
import os
import locale
import sys
from PySide6.QtCore import qVersion
from pathlib import Path
class Constants():
@@ -14,13 +12,6 @@ class Constants():
ORGANIZATION_DOMAIN = 'aresvalley.com'
APPLICATION_VERSION = '4.0.0'
BASE_DIR = Path(os.path.dirname(__file__)) / '../..'
PREFERENCES_DIR = BASE_DIR / 'config'
DB_DIR = BASE_DIR / 'data'
UI_DIR = BASE_DIR / 'ui'
IMAGES_DIR = BASE_DIR / 'images'
LOGS_DIR = BASE_DIR / 'logs'
SQL_NAME = 'data.sqlite'
LATEST_VERSION_URL = 'https://raw.githubusercontent.com/AresValley/Artemis/master/config/release-info.json'
@@ -68,13 +59,13 @@ class Query():
############################## SELECT
SELECT_ALL_SIGNALS = "SELECT SIG_ID, NAME FROM signals ORDER BY NAME ASC"
SELECT_ALL_SIGNALS = "SELECT SIG_ID, NAME, DESCRIPTION FROM signals ORDER BY NAME ASC"
SELECT_ALL_MODULATION = "SELECT DISTINCT VALUE FROM modulation ORDER BY VALUE ASC"
SELECT_ALL_LOCATION = "SELECT DISTINCT VALUE FROM location ORDER BY VALUE ASC"
SELECT_SIG_ID = "SELECT SIG_ID, NAME FROM signals WHERE SIG_ID IN ({}) ORDER BY NAME ASC"
SELECT_SIG_ID = "SELECT SIG_ID, NAME, DESCRIPTION FROM signals WHERE SIG_ID IN ({}) ORDER BY NAME ASC"
SELECT_ALL_CAT_LABELS = "SELECT CLB_ID, VALUE FROM category_label ORDER BY VALUE ASC"

View File

@@ -6,6 +6,7 @@ from packaging.version import Version
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
from artemis.utils.path_utils import DATA_DIR
class NetworkManager:
@@ -14,7 +15,7 @@ class NetworkManager:
def __init__(self, parent):
self._parent = parent
self.sigid_db_path = Constants.DB_DIR / 'sigID' / Constants.SQL_NAME
self.sigid_db_path = DATA_DIR / 'SigID' / Constants.SQL_NAME
self.show_popup = False
self.db_update = None
@@ -92,7 +93,7 @@ class NetworkManager:
""" Loads the local database if exists
"""
if os.path.exists(self.sigid_db_path):
local_db = ArtemisDatabase('sigID')
local_db = ArtemisDatabase('SigID')
local_db.load()
return local_db
return None

View File

@@ -1,14 +1,8 @@
import os
from pathlib import Path
from artemis.utils.sql_utils import ArtemisDatabase
from artemis.utils.constants import Constants
from artemis.utils.sys_utils import *
def check_data_dir():
if not os.path.exists(Constants.DB_DIR):
os.makedirs(Constants.DB_DIR)
from artemis.utils.sys_utils import is_windows, is_linux, is_macos
def normalize_dialog_path(path):
@@ -19,38 +13,37 @@ def normalize_dialog_path(path):
return norm_path
def logs_dir():
def _app_dir():
if is_macos():
logs_dir_path = Path.home() / 'Library/Logs/' / Constants.ORGANIZATION_NAME / Constants.APPLICATION_NAME
app_dir_path = Path.home() / 'Library' / 'Application Support' / Constants.ORGANIZATION_NAME / Constants.APPLICATION_NAME
elif is_windows():
logs_dir_path = Path.home() / 'AppData/Local/' / Constants.ORGANIZATION_NAME / Constants.APPLICATION_NAME / 'logs'
app_dir_path = Path.home() / 'AppData' / 'Local' / Constants.ORGANIZATION_NAME / Constants.APPLICATION_NAME
elif is_linux():
logs_dir_path = Path.home() / '/var/log/' / Constants.ORGANIZATION_NAME / Constants.APPLICATION_NAME
app_dir_path = Path.home() / '.local' / 'share' / Constants.ORGANIZATION_NAME / Constants.APPLICATION_NAME
else:
logs_dir_path = Constants.LOGS_DIR
app_dir_path = BASE_DIR
if not logs_dir_path.exists():
logs_dir_path.mkdir(parents=True)
if not app_dir_path.exists():
app_dir_path.mkdir(parents=True)
return logs_dir_path
return app_dir_path
def valid_db(db_dir_name):
""" Checks if db_dir_name is a valid db dir containing a `data.sqlite` file.
Db must be valid as well and should be properly initialized and loaded with
no errors.
def _data_dir():
data_dir_path = APP_DIR / 'data'
if not data_dir_path.exists():
data_dir_path.mkdir(parents=True)
return data_dir_path
Args:
db_dir_name (str): name of the db folder
"""
if os.path.exists(Constants.DB_DIR / db_dir_name / Constants.SQL_NAME):
try:
database = ArtemisDatabase(db_dir_name)
database.load()
return True
except Exception as e:
# Invalid or corrupted DB
return False
else:
# The dir is not containing a data.sqlite file
return False
def _preference_dir():
preference_dir_path = APP_DIR / 'config'
if not preference_dir_path.exists():
preference_dir_path.mkdir(parents=True)
return preference_dir_path
BASE_DIR = Path(os.path.dirname(__file__)) / '../..'
APP_DIR = _app_dir()
DATA_DIR = _data_dir()
PREFERENCES_DIR = _preference_dir()

View File

@@ -1,13 +1,14 @@
import sqlite3
import os
import sqlite3
from PySide6.QtCore import QUrl
from operator import itemgetter
from datetime import datetime
from contextlib import closing
from artemis.utils.constants import Query, Constants
from artemis.utils.generic_utils import *
from contextlib import closing
from artemis.utils.path_utils import DATA_DIR
from artemis.utils.generic_utils import format_frequency
class Database():
@@ -51,7 +52,7 @@ class ArtemisDatabase(Database):
def __init__(self, db_dir_name):
self.db_dir_name = db_dir_name
self.db_dir = Constants.DB_DIR / db_dir_name
self.db_dir = DATA_DIR / db_dir_name
self.sql_path = self.db_dir / Constants.SQL_NAME
self.media_dir = self.db_dir / 'media'
super().__init__(self.sql_path)
@@ -95,7 +96,7 @@ class ArtemisDatabase(Database):
contains the SIG_ID and the NAME of the signal
"""
self.all_signals = self.execute(Query.SELECT_ALL_SIGNALS)
keys = ('SIG_ID', 'name')
keys = ('SIG_ID', 'name', 'description')
result = [dict(zip(keys, values)) for values in self.all_signals]
self.all_signals = result
@@ -131,7 +132,7 @@ class ArtemisDatabase(Database):
sig_ids = ",".join(str(num[0]) for num in matching_sig_ids)
self.all_signals = self.execute(Query.SELECT_SIG_ID.format(sig_ids))
keys = ('SIG_ID', 'name')
keys = ('SIG_ID', 'name', 'description')
result = [dict(zip(keys, values)) for values in self.all_signals]
self.all_signals = result

View File

@@ -6,7 +6,7 @@ import hashlib
from shutil import rmtree, copyfile, make_archive, unpack_archive
from pathlib import Path
from artemis.utils.constants import Constants, Messages
from artemis.utils.constants import Messages
def is_windows():
@@ -46,29 +46,38 @@ def open_directory(directory, timeout=3):
return
def delete_db_dir(db_dir_name):
"""Delete the db folder"""
db_dir = Constants.DB_DIR / db_dir_name
if os.path.exists(db_dir):
rmtree(db_dir)
def copy_file(src_file_path, dst_file_path):
copyfile(src_file_path, dst_file_path)
def delete_dir(dir_path):
if os.path.exists(dir_path):
rmtree(dir_path)
def delete_file(file_path):
if os.path.exists(file_path):
os.remove(file_path)
def pack_db(save_path, db_dir):
make_archive(save_path, 'tar', db_dir.resolve().as_posix())
def make_tar(save_path, origin_path):
""" Create a tar archive from a folder
Args:
save_path: destination path where new tar is saved
origin_path: directory path of the folder to be archived
"""
make_archive(save_path, 'tar', origin_path.resolve().as_posix())
def unpack_db(tar_path, db_dir_name):
db_dir = Constants.DB_DIR / db_dir_name
unpack_archive(tar_path, db_dir, 'tar')
def unpack_tar(tar_path, destination_path):
""" Unpack a tar archive in a folder
Args:
tar_path: path of the tar to be unpacked
destination_path: path where the tar is extracted
"""
unpack_archive(tar_path, destination_path, 'tar')
def match_hash(data, reference_hash):

View File

@@ -4,7 +4,7 @@ echo "Building Linux target ..."
echo "Installing requirements ..."
pip install -r requirements.txt
pip install nuitka
pip install nuitka==2.3
echo "Building with Nuitka ..."
python -m nuitka app.py \
@@ -12,8 +12,9 @@ python -m nuitka app.py \
--follow-imports \
--show-modules \
--assume-yes-for-downloads \
--disable-console \
--enable-plugin=pyside6 \
--force-stderr-spec="{TEMP}/artemis.err.log" \
--force-stdout-spec="{TEMP}/artemis.out.log" \
--include-qt-plugins=sensible,styles,qml,multimedia \
--include-data-files=./artemis/resources.py=./artemis/resources.py \
--include-data-files=./config/qtquickcontrols2.conf=./config/qtquickcontrols2.conf \

View File

@@ -2,7 +2,7 @@ Write-Output "Building Windows target"
Write-Output "Installing requirements ..."
pip install -r requirements.txt
pip install nuitka
pip install nuitka==2.3
Write-Output "Building with Nuitka ..."
python -m nuitka app.py `
@@ -10,8 +10,10 @@ python -m nuitka app.py `
--follow-imports `
--show-modules `
--assume-yes-for-downloads `
--disable-console `
--windows-console-mode=disable `
--enable-plugin=pyside6 `
--force-stderr-spec="{TEMP}\artemis.err.log" `
--force-stdout-spec="{TEMP}\artemis.out.log" `
--include-qt-plugins=sensible,styles,qml,multimedia `
--include-data-files=.\artemis\resources.py=.\artemis\resources.py `
--include-data-files=.\config\qtquickcontrols2.conf=.\config\qtquickcontrols2.conf `

View File

@@ -42,3 +42,7 @@ Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: de
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
[UninstallDelete]
Type: filesandordirs; Name: "{localappdata}\{#MyAppPublisher}\{#MyAppName}\cache"
Type: filesandordirs; Name: "{localappdata}\{#MyAppPublisher}\{#MyAppName}\config"

View File

@@ -4,7 +4,7 @@ echo "Building maacOS target ..."
echo "Installing requirements ..."
pip install -r requirements.txt
pip install nuitka imageio
pip install nuitka==2.3 imageio
echo "Building with Nuitka ..."
python -m nuitka app.py \
@@ -12,7 +12,6 @@ python -m nuitka app.py \
--follow-imports \
--show-modules \
--assume-yes-for-downloads \
--disable-console \
--enable-plugin=pyside6 \
--include-qt-plugins=sensible,styles,qml,multimedia \
--include-data-files=./artemis/resources.py=./artemis/resources.py \

View File

@@ -1,9 +1,9 @@
{
"sigID_DB": {
"version": 60,
"url": "https://github.com/AresValley/Artemis-DB/releases/download/v60/v60.tar",
"sha256_hash": "78a2c2e5fc00ef4e6c3c975436177eb726fe38ad05463e5cc84b16797225b803",
"total_bytes": 244070400
"version": 61,
"url": "https://github.com/AresValley/Artemis-DB/releases/download/v61/v61.tar",
"sha256_hash": "c65d2ab65e9420cd7789190c100abef2f1575ea15489776c2d97b5b09cdc8410",
"total_bytes": 244449280
},
"windows": {
"version": "4.0.0"

View File

@@ -12,7 +12,7 @@
* **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 simply close the application.
* **Exit:** This will close the application.
### Signal
* **New:** Add a new signal to the database.
@@ -22,7 +22,10 @@
* **Check Report:** Open the main [Space Weather window](space_weather/current.md) and retrieve all the live data from Poseidon Crawler.
## 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. On top of the list, there is a field for filtering signals by name: this filter has the highest priority among all the filters.
This is the signal list where all the database entries are shown. When a signal is selected, it will load on the right panel.
### Filter by Name/Description
On top of the list, there is a field for filtering signals by name or any keyword inside the description of the signal: this filter has the highest priority among all the filters.
## 3. Signal Menu
Here you can swithc between the main **signal** window and the **filter** page.

View File

@@ -1,5 +1,5 @@
# Build Package
Building a distributable package with an executable for Artemis creates a practical solution for end-users, as they can run the application without needing to interact with the terminal and they can easily share the application as a stand-alone package.
Building a distributable package with an executable for Artemis creates a practical solution for end-users, as they can run the application without needing to interact with the terminal and they can easily share the application as a standalone package.
## Requirements
* Python (3.11 or higher)
@@ -8,7 +8,7 @@ Building a distributable package with an executable for Artemis creates a practi
We assume that Python is already installed on the system and the Artemis source code has been downloaded and extracted. If these prerequisites are not met, please follow steps 1 to 3 in the [run from source section](run_from_source.md).
!!! warning "Cross-Compilation"
To generate standalone packages, an operating system that matches the target OS must be used, as Nuitka does not support cross-compilation. For example: you cannot build binaries on Windows that work on Linux or macOS.
An operating system that matches the target OS must be used to generate standalone packages, as Nuitka does not support cross-compilation. For example, you cannot build binaries on Windows that work on Linux or macOS.
## :simple-windows: Windows
@@ -20,7 +20,7 @@ Building a distributable package with an executable for Artemis creates a practi
.\building\Windows\build_windows.ps1
```
2. Wait for the build process to complete. This may take a few minutes depending on your system's performance. Once the process finishes, check the `artemis.dist/` directory: it will contain the stand-alone software with the `artemis.exe` executable.
2. Wait for the build process to complete. This may take a few minutes depending on your system's performance. Once the process finishes, check the `artemis.dist/` directory: it will contain the standalone software with the `artemis.exe` executable.
---
@@ -33,7 +33,7 @@ Building a distributable package with an executable for Artemis creates a practi
. ./building/Linux/build_linux.sh
```
2. Wait for the build process to complete. This may take a few minutes depending on your system's performance. Once the process finishes, check the `artemis.dist/` directory: it will contain the stand-alone software with the `app.bin` executable.
2. Wait for the build process to complete. This may take a few minutes depending on your system's performance. Once the process finishes, check the `artemis.dist/` directory: it will contain the standalone software with the `app.bin` executable.
3. If you wish to create a shortcut, follows the procedure in the [installation section](installation.md/#create-a-shortcut)
---

View File

@@ -1,37 +1,37 @@
# Contribute
Artemis is an open source project an every contribution, no matter how small, is valuable and greatly appreciated. Don't worry about getting everything perfect, we are happy to work with you on your contribution and help you along the way. This guide will help you get started by outlining various ways you can contribute.
Artemis is an open-source project, and every contribution, no matter how small, is valuable and greatly appreciated. Don't worry about getting everything perfect; we are happy to work with you on your contribution and help you along the way. This guide will help you get started by outlining various ways you can contribute.
<div class="grid cards" markdown>
- :material-bug: __Spot a bug?__
- :material-bug: __Spot a bug?__
---
Open an issue (or pull request) and let us know the problem you faced (or you're working on)
Please open an issue (or pull request) and let us know the problem you faced (or you're working on)
[:octicons-arrow-right-24: Open an Issue](https://github.com/AresValley/Artemis/issues)
- :material-source-fork: __Fork the repository__
- :material-source-fork: __Fork the repository__
---
Create your own copy of the codebase that you can modify and submit pull requests from.
Create a copy of the codebase from which you can modify and submit pull requests.
[:octicons-arrow-right-24: Fork the repo](https://github.com/AresValley/Artemis)
- :material-lightbulb-on: __Ideas?__
- :material-lightbulb-on: __Ideas?__
---
Idea for a new feature? Open an issue on the project's GitHub repository to describe your proposal in detail.
Idea for a new feature? Open an issue on the project's GitHub repository to describe your proposal.
[:octicons-arrow-right-24: Open an Issue](https://github.com/AresValley/Artemis/issues)
- :material-heart: __Spreading the word!__
- :material-heart: __Spreading the word!__
---
Do you like Artemis? Don't forgeto to share it with your network and your friends!
Do you like Artemis? Remember to share it with your network and your friends!
</div>

View File

@@ -27,3 +27,18 @@ Running Artemis directly from the source code using the Python interpreter is co
```
pyside6-rcc ./artemis.qrc -o artemis/resources.py
```
## Folders Structure
Artemis can be safely executed and/or installed in any folder (even protected ones, such as `Program Files (x86)` in Windows) because Artemis performs read-only operations in the `BASE_DIR` folder from where it runs. All the reading-writing operations (such as database ops, logging, etc.) are performed in standard folders as follow:
### :simple-windows: Windows
* Data, Cache, Configurations: `$USER\AppData\Local\AresValley\Artemis`
* Logs: `$USER\AppData\Local\Temp`
### :simple-linux: Linux
* Data, Cache, Configurations: `~/.local/share/AresValley/Artemis`
* Logs: `/tmp`
### :simple-apple: Mac OS
* Data, Cache, Configurations: `~/Library/Application Support/AresValley/Artemis`
* Logs: `/tmp`

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#5f6368"><path d="M671-177q-11 7-22 13t-23 11q-15 7-30.5 0T574-176q-6-15 1.5-29.5T598-227q7-3 13-6.5t12-7.5L480-368v111q0 27-24.5 37.5T412-228L280-360H160q-17 0-28.5-11.5T120-400v-160q0-17 11.5-28.5T160-600h88L84-764q-11-11-11-28t11-28q11-11 28-11t28 11l680 680q11 11 11 28t-11 28q-11 11-28 11t-28-11l-93-93Zm89-304q0-83-44-151.5T598-735q-15-7-22-21.5t-2-29.5q6-16 21.5-23t31.5 0q97 43 155 131t58 197q0 33-6 65.5T817-353q-8 22-24.5 27.5t-30.5.5q-14-5-22.5-18t-.5-30q11-26 16-52.5t5-55.5ZM591-623q33 21 51 63t18 80v10q0 5-1 10-2 13-14 17t-22-6l-51-51q-6-6-9-13.5t-3-15.5v-77q0-12 10.5-17.5t20.5.5Zm-201-59q-6-6-6-14t6-14l22-22q19-19 43.5-8.5T480-703v63q0 14-12 19t-22-5l-56-56Z"/></svg>

After

Width:  |  Height:  |  Size: 783 B

View File

@@ -55,8 +55,9 @@ Window {
listModel.clear()
for (var i = 0; i < loadedList.length; i++) {
var name = loadedList[i].name.toLowerCase()
var description = loadedList[i].description.toLowerCase()
var search = textFieldSearch.text.toLowerCase()
if (name.includes(search)) {
if (name.includes(search) || description.includes(search)) {
listModel.append(loadedList[i])
}
}
@@ -214,9 +215,8 @@ Window {
Page {
anchors.fill: parent
leftPadding: 5
rightPadding: 5
bottomPadding: 5
leftPadding: 10
bottomPadding: 10
header: MenuBar {
id: topBar
@@ -320,6 +320,11 @@ Window {
MenuSeparator {}
MenuItem {
text: "Project Homepage"
onClicked: {Qt.openUrlExternally('https://aresvalley.com/')}
}
MenuItem {
text: "Documentation"
onClicked: {Qt.openUrlExternally('https://AresValley.github.io/Artemis')}
@@ -358,16 +363,18 @@ Window {
RowLayout {
anchors.fill: parent
spacing: 20
spacing: 10
ColumnLayout {
Layout.maximumWidth: 250
TextField {
id: textFieldSearch
Layout.preferredHeight: 39
Layout.topMargin: 5
enabled: false
Layout.fillWidth: true
Layout.topMargin: 10
placeholderText: qsTr("Search")
onTextChanged: {
refreshList()
@@ -416,16 +423,14 @@ Window {
TabBar {
id: tabBar
width: parent.width
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
Layout.fillWidth: true
TabButton {
text: qsTr("Signal")
text: qsTr("SIGNAL")
}
TabButton {
text: qsTr("Filter")
text: qsTr("FILTERS")
}
}

View File

@@ -213,6 +213,8 @@ Page {
ColumnLayout {
anchors.fill: parent
anchors.rightMargin: 10
anchors.topMargin: 10
GridLayout {
rows: 2

View File

@@ -67,10 +67,10 @@ Window {
ColumnLayout {
anchors.fill: parent
anchors.rightMargin: 15
anchors.leftMargin: 15
anchors.bottomMargin: 15
anchors.topMargin: 15
anchors.rightMargin: 10
anchors.leftMargin: 10
anchors.bottomMargin: 10
anchors.topMargin: 10
RowLayout {
Layout.fillWidth: true

View File

@@ -168,6 +168,8 @@ Page {
ColumnLayout {
anchors.fill: parent
anchors.rightMargin: 10
anchors.topMargin: 10
Label {
id: signalName

View File

@@ -34,10 +34,10 @@ Page {
ColumnLayout {
anchors.fill: parent
anchors.rightMargin: 20
anchors.leftMargin: 20
anchors.bottomMargin: 20
anchors.topMargin: 20
anchors.rightMargin: 10
anchors.leftMargin: 10
anchors.bottomMargin: 10
anchors.topMargin: 10
Image {
id: imageBox

View File

@@ -79,10 +79,10 @@ Page {
RowLayout {
anchors.fill: parent
anchors.rightMargin: 20
anchors.leftMargin: 20
anchors.bottomMargin: 20
anchors.topMargin: 20
anchors.rightMargin: 10
anchors.leftMargin: 10
anchors.bottomMargin: 10
anchors.topMargin: 10
ColumnLayout {
Layout.fillHeight: true

View File

@@ -38,10 +38,10 @@ Page {
ColumnLayout {
anchors.fill: parent
anchors.rightMargin: 20
anchors.leftMargin: 20
anchors.bottomMargin: 20
anchors.topMargin: 20
anchors.rightMargin: 10
anchors.leftMargin: 10
anchors.bottomMargin: 10
anchors.topMargin: 10
Image {
id: imageBox

View File

@@ -120,10 +120,10 @@ Page {
ColumnLayout {
anchors.fill: parent
anchors.rightMargin: 20
anchors.leftMargin: 20
anchors.bottomMargin: 20
anchors.topMargin: 20
anchors.rightMargin: 10
anchors.leftMargin: 10
anchors.bottomMargin: 10
anchors.topMargin: 10
ColumnLayout {
Layout.fillHeight: true

View File

@@ -7,8 +7,8 @@ import QtMultimedia
Item {
width: 200
height: 80
width: 180
height: 132
property bool loop: false
@@ -28,7 +28,7 @@ Item {
buttonPause.enabled = true
buttonStop.enabled = true
buttonLoop.enabled = true
playerPosition.enabled = player.seekable
positionSlider.enabled = player.seekable
player.play()
}
@@ -65,10 +65,12 @@ Item {
buttonPause.enabled = false
buttonStop.enabled = false
buttonLoop.enabled = false
playerPosition.enabled = false
positionSlider.enabled = false
}
ColumnLayout {
anchors.fill: parent
spacing: 0
RowLayout {
spacing: 0
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
@@ -83,6 +85,10 @@ Item {
onClicked: playSound()
}
Item {
Layout.fillWidth: true
}
RoundButton {
id: buttonPause
icon.color: Material.foreground
@@ -93,6 +99,10 @@ Item {
onClicked: pauseSound()
}
Item {
Layout.fillWidth: true
}
RoundButton {
id: buttonStop
icon.color: Material.foreground
@@ -103,6 +113,10 @@ Item {
onClicked: stopSound()
}
Item {
Layout.fillWidth: true
}
RoundButton {
id: buttonLoop
icon.color: Material.foreground
@@ -122,21 +136,43 @@ Item {
}
}
Slider {
id: playerPosition
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
Layout.preferredHeight: 20
enabled: player.seekable
value: player.duration > 0 ? player.position / player.duration : 0
onMoved: {
player.position = player.duration * playerPosition.position
RowLayout {
Slider {
id: positionSlider
Layout.preferredHeight: 20
enabled: player.seekable
value: player.duration > 0 ? player.position / player.duration : 0
Layout.fillWidth: true
onMoved: {
player.position = player.duration * positionSlider.position
}
}
}
RowLayout {
Slider {
id: volumeSlider
Layout.preferredHeight: 20
value: 0.5
Layout.fillWidth: true
}
RoundButton {
id: buttonMute
icon.color: Material.foreground
icon.source: "qrc:/images/icons/player_mute.svg"
display: AbstractButton.IconOnly
enabled: true
flat: true
onClicked: {
volumeSlider.value = 0
}
}
}
MediaPlayer {
id: player
audioOutput: audioOutput
onPlaybackStateChanged: {
if (player.playbackState === MediaPlayer.StoppedState) {
if (loop) {
@@ -150,7 +186,7 @@ Item {
AudioOutput {
id: audioOutput
//volume: volumeSlider.value
volume: volumeSlider.value
}
}
}