diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..80c8292
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..306f5f3
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..ed491e5
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..cc5462d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..a6525a8
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..292ffec
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/.idea/tidal-dl-ng.iml b/.idea/tidal-dl-ng.iml
new file mode 100644
index 0000000..64c736c
--- /dev/null
+++ b/.idea/tidal-dl-ng.iml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..dcb6b8c
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/tidal_dl_ng/constants.py b/tidal_dl_ng/constants.py
index 802fedf..e5a877f 100644
--- a/tidal_dl_ng/constants.py
+++ b/tidal_dl_ng/constants.py
@@ -52,6 +52,14 @@ class QueueDownloadStatus(StrEnum):
Skipped: str = "↪️"
+class SearchTypes(StrEnum):
+ Track: str = "Track"
+ Video: str = "Video"
+ Playlist: str = "Playlist"
+ Album: str = "Album"
+ Artist: str = "Artist"
+
+
FAVORITES: {} = {
"fav_videos": {"name": "Videos", "function_name": "videos"},
"fav_tracks": {"name": "Tracks", "function_name": "tracks"},
diff --git a/tidal_dl_ng/gui.py b/tidal_dl_ng/gui.py
index 870b658..8341dad 100644
--- a/tidal_dl_ng/gui.py
+++ b/tidal_dl_ng/gui.py
@@ -48,7 +48,10 @@
import sys
import time
from collections.abc import Callable, Sequence
+from copy import deepcopy
+from functools import partial
+from PySide6.QtGui import QAction
from requests.exceptions import HTTPError
from tidalapi.session import LinkLogin
@@ -148,6 +151,10 @@ def __init__(self, tidal: Tidal | None = None):
# XStream.stderr().messageWritten.connect(self._log_output)
self.settings = Settings()
+ # Default result tree list context menu items
+ self.tr_results_headers_ctx_items: list[str] = []
+ # Loads previously saved Result Tree Header from settings
+ self._load_rt_from_settings()
self._init_threads()
self._init_tree_results_model(self.model_tr_results)
@@ -272,7 +279,18 @@ def _populate_search_types(self, ui_target: QtWidgets.QComboBox, options: Search
if item:
ui_target.addItem(item.__name__, item)
- self.cb_search_type.setCurrentIndex(2)
+ search_type = self.settings.data.search_type.capitalize()
+ # sets the last used Search type
+ self.cb_search_type.setCurrentIndex(self.cb_search_type.findText(search_type))
+ # self.cb_search_type.setCurrentIndex(2)
+
+ def _save_cb_search_type(self):
+ """
+ Save the last used search type when changing it
+ """
+ search_type = self.cb_search_type.currentText()
+ self.settings.data.search_type = search_type
+ self.settings.save()
def handle_filter_activated(self):
header: FilterHeader = self.tr_results.header()
@@ -307,6 +325,26 @@ def _init_tree_results(self, tree: QtWidgets.QTreeView, model: QtGui.QStandardIt
# Connect the contextmenu
tree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
tree.customContextMenuRequested.connect(self.menu_context_tree_results)
+ # Connect Header visibility context menu
+ tree.header().setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
+ tree.header().customContextMenuRequested.connect(self.menu_context_tree_headers)
+
+ hidden = []
+ labels_column: [str] = deepcopy(self.tr_results_headers_ctx_items)
+ for index, item in enumerate(labels_column):
+ if "obj" in item:
+ continue
+ if "❌" in item:
+ if "#" not in item:
+ index += 1
+ hidden.append(index)
+ labels_column[index] = item.replace("❌", "")
+ elif "✅" in item:
+ if "#" not in item:
+ index += 1
+ labels_column[index] = item.replace("✅", "")
+ for i in hidden:
+ tree.setColumnHidden(i, True)
def _init_tree_results_model(self, model: QtGui.QStandardItemModel) -> None:
labels_column: [str] = ["#", "obj", "Artist", "Title", "Album", "Duration", "Quality", "Date Added"]
@@ -315,6 +353,44 @@ def _init_tree_results_model(self, model: QtGui.QStandardItemModel) -> None:
model.setRowCount(0)
model.setHorizontalHeaderLabels(labels_column)
+ def _load_rt_from_settings(self):
+ settings = self.settings.data
+ for i in settings.rt_header_ctx.split(","):
+ if "obj" in i:
+ continue
+ self.tr_results_headers_ctx_items.append(i)
+
+ def menu_context_tree_headers(self):
+ """
+ Adds context menu to the header of the result tree list
+ """
+ menu = QtWidgets.QMenu()
+ for m in self.tr_results_headers_ctx_items:
+ action = QAction(m, self)
+ action.triggered.connect(partial(self._toggle_header_section_hidden, m))
+ menu.addAction(action)
+
+ menu.exec(QtGui.QCursor.pos())
+
+ def _toggle_header_section_hidden(self, item: str):
+ """
+ Toggles result tree list columns visibility
+ Then save the changes to settings
+ """
+ index = self.tr_results_headers_ctx_items.index(item)
+ is_visible = "✅" in item
+ new_label = item.replace("✅" if is_visible else "❌", "❌" if is_visible else "✅")
+ self.tr_results_headers_ctx_items[index] = new_label
+ if "#" not in item:
+ index += 1
+
+ self.tr_results.header().setSectionHidden(index, is_visible)
+ updated_tr_results_headers_ctx_items = deepcopy(self.tr_results_headers_ctx_items)
+ updated_tr_results_headers_ctx_items.insert(1, "✅obj")
+ self.settings.data.rt_header_ctx = ""
+ self.settings.data.rt_header_ctx = ",".join(updated_tr_results_headers_ctx_items)
+ self.settings.save()
+
def _init_tree_queue(self, tree: QtWidgets.QTableWidget):
tree.setColumnHidden(1, True)
tree.setColumnWidth(2, 200)
@@ -759,6 +835,7 @@ def _init_signals(self):
self.pb_search.clicked.connect(
lambda: self.search_populate_results(self.l_search.text(), self.cb_search_type.currentData())
)
+ self.cb_search_type.currentIndexChanged.connect(lambda: self._save_cb_search_type())
self.cb_quality_audio.currentIndexChanged.connect(self.on_quality_set_audio)
self.cb_quality_video.currentIndexChanged.connect(self.on_quality_set_video)
self.tr_lists_user.itemClicked.connect(self.on_list_items_show)
diff --git a/tidal_dl_ng/model/cfg.py b/tidal_dl_ng/model/cfg.py
index 69c394d..7a6f70a 100644
--- a/tidal_dl_ng/model/cfg.py
+++ b/tidal_dl_ng/model/cfg.py
@@ -3,7 +3,7 @@
from dataclasses_json import dataclass_json
from tidalapi import Quality
-from tidal_dl_ng.constants import CoverDimensions, QualityVideo
+from tidal_dl_ng.constants import CoverDimensions, QualityVideo, SearchTypes
@dataclass_json
@@ -45,6 +45,8 @@ class Settings:
symlink_to_track: bool = False
playlist_create: bool = False
metadata_replay_gain: bool = True
+ search_type: SearchTypes = SearchTypes.Track
+ rt_header_ctx: str = "✅#,✅obj,✅Artist,✅Title,✅Album,✅Duration,✅Quality,✅Date Added"
@dataclass_json
@@ -99,6 +101,8 @@ class HelpSettings:
)
playlist_create: str = "Creates a '_playlist.m3u8' file for downloaded albums, playlists and mixes."
metadata_replay_gain: str = "Replay gain information will be written to metadata."
+ search_type: str = "Search for tracks by artist, album or track name."
+ rt_header_ctx: str = "Result Tree List columns visibility."
@dataclass_json