Files
tidal-dl/tidal_dl_ng/dialog.py
T

284 lines
10 KiB
Python
Raw Normal View History

2024-11-13 13:26:46 +01:00
import datetime
2024-02-04 12:19:40 +01:00
import os.path
import shutil
import webbrowser
2024-04-03 07:09:15 +02:00
from enum import Enum, StrEnum
2024-02-04 12:19:40 +01:00
from pathlib import Path
from PySide6 import QtCore, QtGui, QtWidgets
from tidalapi import Quality as QualityAudio
2024-01-19 10:00:27 +01:00
from tidal_dl_ng import __version__
2024-02-04 12:50:19 +01:00
from tidal_dl_ng.config import Settings
from tidal_dl_ng.constants import CoverDimensions, QualityVideo
2024-02-04 12:19:40 +01:00
from tidal_dl_ng.model.cfg import HelpSettings
from tidal_dl_ng.model.cfg import Settings as ModelSettings
from tidal_dl_ng.model.meta import ReleaseLatest
from tidal_dl_ng.ui.dialog_login import Ui_DialogLogin
2024-02-04 12:19:40 +01:00
from tidal_dl_ng.ui.dialog_settings import Ui_DialogSettings
2024-01-19 10:00:27 +01:00
from tidal_dl_ng.ui.dialog_version import Ui_DialogVersion
2024-02-04 12:19:40 +01:00
class DialogVersion(QtWidgets.QDialog):
2024-01-19 10:00:27 +01:00
"""Version dialog."""
2024-02-04 12:19:40 +01:00
ui: Ui_DialogVersion
def __init__(
self, parent=None, update_check: bool = False, update_available: bool = False, update_info: ReleaseLatest = None
):
2024-01-19 10:00:27 +01:00
super().__init__(parent)
2024-01-19 10:00:27 +01:00
# Create an instance of the GUI
self.ui = Ui_DialogVersion()
2024-01-19 10:00:27 +01:00
# Run the .setupUi() method to show the GUI
self.ui.setupUi(self)
# Set the version.
self.ui.l_version.setText("v" + __version__)
if not update_check:
self.update_info_hide()
self.error_hide()
else:
self.update_info(update_available, update_info)
# Show
2024-01-19 10:00:27 +01:00
self.exec()
def update_info(self, update_available: bool, update_info: ReleaseLatest):
if not update_available and update_info.version == "v0.0.0":
self.update_info_hide()
self.ui.l_error_details.setText(
"Cannot retrieve update information. Maybe something is wrong with your internet connection."
)
else:
self.error_hide()
if not update_available:
self.ui.l_h_version_new.setText("Latest available version:")
self.changelog_hide()
else:
self.ui.l_changelog_details.setText(update_info.release_info)
self.ui.pb_download.clicked.connect(lambda: webbrowser.open(update_info.url))
self.ui.l_version_new.setText(update_info.version)
def error_hide(self):
self.ui.l_error.setHidden(True)
self.ui.l_error_details.setHidden(True)
def update_info_hide(self):
self.ui.l_h_version_new.setHidden(True)
self.ui.l_version_new.setHidden(True)
self.changelog_hide()
def changelog_hide(self):
self.ui.l_changelog.setHidden(True)
self.ui.l_changelog_details.setHidden(True)
self.ui.pb_download.setHidden(True)
2024-02-04 12:19:40 +01:00
class DialogLogin(QtWidgets.QDialog):
"""Version dialog."""
2024-02-04 12:19:40 +01:00
ui: Ui_DialogLogin
url_redirect: str
def __init__(self, url_login: str, hint: str, expires_in: int, parent=None):
super().__init__(parent)
datetime_current: datetime.datetime = datetime.datetime.now()
datetime_expires: datetime.datetime = datetime_current + datetime.timedelta(0, expires_in)
# Create an instance of the GUI
self.ui = Ui_DialogLogin()
# Run the .setupUi() method to show the GUI
self.ui.setupUi(self)
# Set data.
self.ui.tb_url_login.setText(f'<a href="https://{url_login}">https://{url_login}</a>')
self.ui.l_hint.setText(hint)
self.ui.l_expires_date_time.setText(datetime_expires.strftime("%Y-%m-%d %H:%M"))
# Show
self.return_code = self.exec()
2024-02-04 12:19:40 +01:00
class DialogPreferences(QtWidgets.QDialog):
"""Preferences dialog."""
ui: Ui_DialogSettings
2024-02-04 12:50:19 +01:00
settings: Settings
data: ModelSettings
s_settings_save: QtCore.Signal
2024-02-04 12:19:40 +01:00
icon: QtGui.QIcon
help_settings: HelpSettings
2024-02-04 12:50:19 +01:00
parameters_checkboxes: [str]
2024-04-02 16:16:38 +02:00
parameters_combo: [(str, StrEnum)]
2024-02-04 12:50:19 +01:00
parameters_line_edit: [str]
prefix_checkbox: str = "cb_"
prefix_label: str = "l_"
prefix_icon: str = "icon_"
prefix_line_edit: str = "le_"
prefix_combo: str = "c_"
2024-02-04 12:19:40 +01:00
2024-02-04 12:50:19 +01:00
def __init__(self, settings: Settings, settings_save: QtCore.Signal, parent=None):
2024-02-04 12:19:40 +01:00
super().__init__(parent)
self.settings = settings
2024-02-04 12:50:19 +01:00
self.data = settings.data
self.s_settings_save = settings_save
2024-02-04 12:19:40 +01:00
self.help_settings = HelpSettings()
pixmapi: QtWidgets.QStyle.StandardPixmap = QtWidgets.QStyle.SP_MessageBoxQuestion
self.icon = self.style().standardIcon(pixmapi)
self._init_checkboxes()
self._init_comboboxes()
self._init_line_edit()
# Create an instance of the GUI
self.ui = Ui_DialogSettings()
# Run the .setupUi() method to show the GUI
self.ui.setupUi(self)
# Set data.
self.gui_populate()
self.exec()
def _init_line_edit(self):
2024-02-04 12:50:19 +01:00
self.parameters_line_edit = [
"download_base_path",
"format_album",
"format_playlist",
"format_mix",
"format_track",
"format_video",
2024-03-29 10:54:04 +01:00
"path_binary_ffmpeg",
2024-02-04 12:50:19 +01:00
]
def _init_comboboxes(self):
self.parameters_combo = [
("quality_audio", QualityAudio),
("quality_video", QualityVideo),
("metadata_cover_dimension", CoverDimensions),
]
2024-02-04 12:19:40 +01:00
def _init_checkboxes(self):
self.parameters_checkboxes = [
"lyrics_embed",
"lyrics_file",
"video_download",
"download_delay",
"video_convert_mp4",
"extract_flac",
2024-11-11 10:17:10 +01:00
"metadata_cover_embed",
"cover_album_file",
"skip_existing",
]
2024-02-04 12:19:40 +01:00
def gui_populate(self):
self.populate_checkboxes()
self.populate_combo()
self.populate_line_edit()
2024-03-29 10:54:04 +01:00
def dialog_chose_file(
self,
obj_line_edit: QtWidgets.QLineEdit,
file_mode: QtWidgets.QFileDialog | QtWidgets.QFileDialog.FileMode = QtWidgets.QFileDialog.Directory,
path_default: str = None,
2024-03-29 10:54:04 +01:00
):
2024-02-04 12:19:40 +01:00
# If a path is set, use it otherwise the users home directory.
path_settings: str = os.path.expanduser(obj_line_edit.text()) if obj_line_edit.text() else ""
# Check if obj_line_edit is empty but path_default can be usd instead
path_settings = (
path_settings if path_settings else os.path.expanduser(path_default) if path_default else path_settings
)
dir_current: str = path_settings if path_settings and os.path.exists(path_settings) else str(Path.home())
2024-03-29 10:54:04 +01:00
dialog: QtWidgets.QFileDialog = QtWidgets.QFileDialog()
2024-02-04 12:19:40 +01:00
# Set to directory mode only but show files.
2024-03-29 10:54:04 +01:00
dialog.setFileMode(file_mode)
2024-02-04 12:19:40 +01:00
dialog.setViewMode(QtWidgets.QFileDialog.Detail)
dialog.setOption(QtWidgets.QFileDialog.ShowDirsOnly, False)
2024-03-29 10:54:04 +01:00
dialog.setOption(QtWidgets.QFileDialog.DontResolveSymlinks, True)
2024-02-04 12:19:40 +01:00
# There is a bug in the PyQt implementation, which hides files in Directory mode.
# Thus, we need to use the PyQt dialog instead of the native dialog.
2024-03-29 10:54:04 +01:00
if os.name == "nt" and file_mode == QtWidgets.QFileDialog.Directory:
2024-02-04 12:19:40 +01:00
dialog.setOption(QtWidgets.QFileDialog.DontUseNativeDialog, True)
2024-03-29 10:54:04 +01:00
2024-02-04 12:19:40 +01:00
dialog.setDirectory(dir_current)
# Execute dialog and set path is something is choosen.
if dialog.exec():
2024-03-29 10:54:04 +01:00
dir_name: str = dialog.selectedFiles()[0]
path: Path = Path(dir_name)
2024-02-04 12:19:40 +01:00
obj_line_edit.setText(str(path))
def populate_line_edit(self):
2024-02-04 12:50:19 +01:00
for pn in self.parameters_line_edit:
label_icon: QtWidgets.QLabel = getattr(self.ui, self.prefix_label + self.prefix_icon + pn)
label: QtWidgets.QLabel = getattr(self.ui, self.prefix_label + pn)
line_edit: QtWidgets.QLineEdit = getattr(self.ui, self.prefix_line_edit + pn)
2024-02-04 12:19:40 +01:00
label_icon.setPixmap(QtGui.QPixmap(self.icon.pixmap(QtCore.QSize(16, 16))))
label_icon.setToolTip(getattr(self.help_settings, pn))
label.setText(pn)
2024-02-04 12:50:19 +01:00
line_edit.setText(getattr(self.data, pn))
2024-02-04 12:19:40 +01:00
# Base Path File Dialog
2024-03-29 10:54:04 +01:00
self.ui.pb_download_base_path.clicked.connect(lambda x: self.dialog_chose_file(self.ui.le_download_base_path))
self.ui.pb_path_binary_ffmpeg.clicked.connect(
lambda x: self.dialog_chose_file(
self.ui.le_path_binary_ffmpeg,
file_mode=QtWidgets.QFileDialog.FileMode.ExistingFiles,
path_default=shutil.which("ffmpeg"),
2024-03-29 10:54:04 +01:00
)
)
2024-02-04 12:19:40 +01:00
def populate_combo(self):
2024-02-04 12:50:19 +01:00
for p in self.parameters_combo:
2024-02-04 12:19:40 +01:00
pn: str = p[0]
values: Enum = p[1]
2024-02-04 12:50:19 +01:00
label_icon: QtWidgets.QLabel = getattr(self.ui, self.prefix_label + self.prefix_icon + pn)
label: QtWidgets.QLabel = getattr(self.ui, self.prefix_label + pn)
combo: QtWidgets.QComboBox = getattr(self.ui, self.prefix_combo + pn)
setting_current = getattr(self.data, pn)
2024-02-04 12:19:40 +01:00
label_icon.setPixmap(QtGui.QPixmap(self.icon.pixmap(QtCore.QSize(16, 16))))
label_icon.setToolTip(getattr(self.help_settings, pn))
label.setText(pn)
for index, v in enumerate(values):
combo.addItem(v.name, v)
if v == setting_current:
combo.setCurrentIndex(index)
def populate_checkboxes(self):
2024-02-04 12:50:19 +01:00
for pn in self.parameters_checkboxes:
checkbox: QtWidgets.QCheckBox = getattr(self.ui, self.prefix_checkbox + pn)
2024-02-04 12:19:40 +01:00
checkbox.setText(pn)
checkbox.setToolTip(getattr(self.help_settings, pn))
checkbox.setIcon(self.icon)
2024-02-04 12:50:19 +01:00
checkbox.setChecked(getattr(self.data, pn))
2024-02-04 12:19:40 +01:00
def accept(self):
# Get settings.
2024-02-04 12:50:19 +01:00
self.to_settings()
self.done(1)
def to_settings(self):
for item in self.parameters_checkboxes:
setattr(self.settings.data, item, getattr(self.ui, self.prefix_checkbox + item).isChecked())
for item in self.parameters_line_edit:
setattr(self.settings.data, item, getattr(self.ui, self.prefix_line_edit + item).text())
for item in self.parameters_combo:
setattr(self.settings.data, item[0], getattr(self.ui, self.prefix_combo + item[0]).currentData())
self.s_settings_save.emit()