mirror of
https://github.com/yaronzz/Tidal-Media-Downloader.git
synced 2026-01-16 16:04:25 -05:00
upload new version
This commit is contained in:
Binary file not shown.
3
TIDALDL-PY/guiStatic.in
Normal file
3
TIDALDL-PY/guiStatic.in
Normal file
@@ -0,0 +1,3 @@
|
||||
include tidal_gui/resource/themeDefault.qss
|
||||
include tidal_gui/resource/svg/*.svg
|
||||
include tidal_gui/resource/svg/*/*.svg
|
||||
@@ -4,5 +4,5 @@ prettytable==0.7.2
|
||||
mutagen==1.45.1
|
||||
psutil==5.7.3
|
||||
pycryptodome==3.9.9
|
||||
aigpy==2021.9.10.3
|
||||
aigpy==2022.01.18.2
|
||||
lyricsgenius==3.0.1
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
from setuptools import setup, find_packages
|
||||
setup(
|
||||
name = 'tidal-gui',
|
||||
version = '1.0.0.4',
|
||||
version = '2022.01.18.3',
|
||||
license = "Apache2",
|
||||
description = "Tidal Music Downloader.",
|
||||
description = "Tidal Music Downloader-GUI.",
|
||||
|
||||
author = 'YaronH',
|
||||
author_email = "yaronhuang@foxmail.com",
|
||||
|
||||
packages = find_packages(),
|
||||
packages=find_packages(exclude=['tidal_dl*']),
|
||||
include_package_data = True,
|
||||
platforms = "any",
|
||||
install_requires=["aigpy", "PyQt5", "requests>=2.22.0", "pycryptodome", "pydub", "prettytable", "lyricsgenius"],
|
||||
install_requires=["tidal-dl", "PyQt5"],
|
||||
entry_points={'console_scripts': [ 'tidal-gui = tidal_gui:main', ]}
|
||||
)
|
||||
|
||||
@@ -10,9 +10,10 @@ setup(
|
||||
author='YaronH',
|
||||
author_email="yaronhuang@foxmail.com",
|
||||
|
||||
packages=find_packages(),
|
||||
include_package_data=True,
|
||||
packages=find_packages(exclude=['tidal_gui*']),
|
||||
include_package_data=False,
|
||||
platforms="any",
|
||||
install_requires=["aigpy>=2021.12.10.1", "requests>=2.22.0", "pycryptodome", "pydub", "prettytable", "lyricsgenius"],
|
||||
install_requires=["aigpy>=2022.01.18.2", "requests>=2.22.0",
|
||||
"pycryptodome", "pydub", "prettytable", "lyricsgenius"],
|
||||
entry_points={'console_scripts': ['tidal-dl = tidal_dl:main', ]}
|
||||
)
|
||||
|
||||
@@ -30,7 +30,7 @@ __LOGO__ = '''
|
||||
|
||||
https://github.com/yaronzz/Tidal-Media-Downloader
|
||||
'''
|
||||
VERSION = '2022.01.11.1'
|
||||
VERSION = '2022.01.18.2'
|
||||
|
||||
|
||||
class Printf(object):
|
||||
|
||||
@@ -301,10 +301,32 @@ def encrypted(stream, srcPath, descPath):
|
||||
def getAudioQualityList():
|
||||
return map(lambda quality: quality.name, tidal_dl.enums.AudioQuality)
|
||||
|
||||
def getCurAudioQuality():
|
||||
return CONF.audioQuality.name
|
||||
|
||||
def setCurAudioQuality(text):
|
||||
if CONF.audioQuality.name == text:
|
||||
return
|
||||
for item in tidal_dl.enums.AudioQuality:
|
||||
if item.name == text:
|
||||
CONF.audioQuality = item
|
||||
break
|
||||
Settings.save(CONF)
|
||||
|
||||
def getVideoQualityList():
|
||||
return map(lambda quality: quality.name, tidal_dl.enums.VideoQuality)
|
||||
|
||||
def getCurVideoQuality():
|
||||
return CONF.videoQuality.name
|
||||
|
||||
def setCurVideoQuality(text):
|
||||
if CONF.videoQuality.name == text:
|
||||
return
|
||||
for item in tidal_dl.enums.VideoQuality:
|
||||
if item.name == text:
|
||||
CONF.videoQuality = item
|
||||
break
|
||||
Settings.save(CONF)
|
||||
|
||||
def skip(path, url):
|
||||
if CONF.checkExist and isNeedDownload(path, url) is False:
|
||||
|
||||
@@ -66,7 +66,10 @@ class FramelessWidget(QWidget):
|
||||
|
||||
def __clickInValidMoveWidget__(self, x=-1, y=-1) -> bool:
|
||||
if self.validMoveWidget is None:
|
||||
return True
|
||||
return False
|
||||
if self.clickPos is None:
|
||||
return False
|
||||
|
||||
if x == -1 and y == -1:
|
||||
x = self.clickPos.x()
|
||||
y = self.clickPos.y()
|
||||
|
||||
@@ -29,6 +29,10 @@ class ScrollWidget(QScrollArea):
|
||||
def addWidgetItem(self, widget: QWidget):
|
||||
self._layout.insertWidget(self._numWidget, widget)
|
||||
self._numWidget += 1
|
||||
|
||||
def delWidgetItem(self, widget: QWidget):
|
||||
self._layout.removeWidget(widget)
|
||||
self._numWidget -= 1
|
||||
|
||||
def resizeEvent(self, e: QResizeEvent):
|
||||
super().resizeEvent(e)
|
||||
|
||||
@@ -74,8 +74,8 @@ class MainView(FramelessWidget):
|
||||
layout.addWidget(self._searchBtn)
|
||||
layout.addWidget(self._taskBtn)
|
||||
layout.addStretch(1)
|
||||
layout.addWidget(self._settingsBtn)
|
||||
layout.addWidget(self._aboutBtn)
|
||||
# layout.addWidget(self._settingsBtn)
|
||||
# layout.addWidget(self._aboutBtn)
|
||||
|
||||
widget = QWidget()
|
||||
widget.setLayout(layout)
|
||||
@@ -119,6 +119,5 @@ class MainView(FramelessWidget):
|
||||
self.__setContentPage__(view, PageType.Settings)
|
||||
|
||||
def setAboutView(self, view: QWidget):
|
||||
# self.__setContentPage__(view, PageType.About)
|
||||
self._pages[PageType.About] = view
|
||||
self._pages[PageType.About].hide()
|
||||
|
||||
@@ -198,11 +198,15 @@ class SearchView(QWidget):
|
||||
return -1
|
||||
return array[0].row()
|
||||
|
||||
def setTrackQualityItems(self, items: list):
|
||||
def setTrackQualityItems(self, items: list, curItem = None):
|
||||
self._trackQualityComboBox.setItems(items)
|
||||
if curItem is not None:
|
||||
self._trackQualityComboBox.setCurrentText(curItem)
|
||||
|
||||
def setVideoQualityItems(self, items: list):
|
||||
def setVideoQualityItems(self, items: list, curItem=None):
|
||||
self._videoQualityComboBox.setItems(items)
|
||||
if curItem is not None:
|
||||
self._videoQualityComboBox.setCurrentText(curItem)
|
||||
|
||||
def getTrackQualityText(self):
|
||||
return self._trackQualityComboBox.currentText()
|
||||
@@ -222,3 +226,9 @@ class SearchView(QWidget):
|
||||
|
||||
def connectTab(self, func):
|
||||
self._tabWidget.currentChanged.connect(func)
|
||||
|
||||
def connectQualityComboBox(self, name: str, func):
|
||||
if name == 'track':
|
||||
self._trackQualityComboBox.currentIndexChanged.connect(func)
|
||||
else:
|
||||
self._videoQualityComboBox.currentIndexChanged.connect(func)
|
||||
|
||||
@@ -21,7 +21,7 @@ from tidal_gui.style import LabelStyle, ListWidgetStyle
|
||||
from tidal_gui.theme import getResourcePath
|
||||
|
||||
|
||||
class TaskListType(Enum):
|
||||
class TaskStatus(Enum):
|
||||
Download = 0,
|
||||
Complete = 1,
|
||||
Error = 2,
|
||||
@@ -33,18 +33,18 @@ class TaskView(QWidget):
|
||||
self._listMap = {}
|
||||
self._pageMap = {}
|
||||
|
||||
for item in map(lambda typeItem: typeItem.name, TaskListType):
|
||||
for item in map(lambda typeItem: typeItem.name, TaskStatus):
|
||||
self._listMap[item] = ScrollWidget()
|
||||
self._pageMap[item] = QWidget()
|
||||
|
||||
self.__initView__()
|
||||
self._listTab.setCurrentRow(0)
|
||||
self._pageMap[TaskListType.Download.name].show()
|
||||
self._pageMap[TaskStatus.Download.name].show()
|
||||
|
||||
def __initView__(self):
|
||||
grid = QGridLayout(self)
|
||||
grid.addLayout(self.__initLefTab__(), 0, 0, Qt.AlignLeft)
|
||||
for item in map(lambda typeItem: typeItem.name, TaskListType):
|
||||
for item in map(lambda typeItem: typeItem.name, TaskStatus):
|
||||
grid.addWidget(self.__createContent__(item), 0, 1)
|
||||
|
||||
def __initLefTab__(self):
|
||||
@@ -52,9 +52,9 @@ class TaskView(QWidget):
|
||||
self._listTab.setIconSize(QSize(20, 20))
|
||||
|
||||
iconPath = getResourcePath() + "/svg/taskTab/"
|
||||
self._listTab.addIConTextItem(iconPath + 'download.svg', TaskListType.Download.name)
|
||||
self._listTab.addIConTextItem(iconPath + 'complete.svg', TaskListType.Complete.name)
|
||||
self._listTab.addIConTextItem(iconPath + 'error.svg', TaskListType.Error.name)
|
||||
self._listTab.addIConTextItem(iconPath + 'download.svg', TaskStatus.Download.name)
|
||||
self._listTab.addIConTextItem(iconPath + 'complete.svg', TaskStatus.Complete.name)
|
||||
self._listTab.addIConTextItem(iconPath + 'error.svg', TaskStatus.Error.name)
|
||||
|
||||
self._listTab.itemClicked.connect(self.__tabItemChanged__)
|
||||
|
||||
@@ -83,5 +83,8 @@ class TaskView(QWidget):
|
||||
else:
|
||||
self._pageMap[name].hide()
|
||||
|
||||
def addItemView(self, stype: TaskListType, view):
|
||||
def addItemView(self, stype: TaskStatus, view):
|
||||
self._listMap[stype.name].addWidgetItem(view)
|
||||
|
||||
def delItemView(self, stype: TaskStatus, view):
|
||||
self._listMap[stype.name].delWidgetItem(view)
|
||||
|
||||
@@ -16,6 +16,7 @@ from enum import Enum
|
||||
from pickle import FALSE
|
||||
from aigpy.downloadHelper import UserProgress
|
||||
import aigpy.stringHelper
|
||||
from PyQt5.QtCore import pyqtSignal
|
||||
|
||||
from tidal_dl.model import Track
|
||||
from tidal_dl.util import downloadTrack, downloadVideo, getArtistsNames, setMetaData
|
||||
@@ -60,6 +61,8 @@ class Progress(UserProgress):
|
||||
|
||||
|
||||
class DownloadItemModel(ViewModel):
|
||||
SIGNAL_END = pyqtSignal(DownloadStatus)
|
||||
|
||||
def __init__(self, index, data, basePath):
|
||||
super(DownloadItemModel, self).__init__()
|
||||
self.view = DownloadItemView()
|
||||
@@ -94,11 +97,13 @@ class DownloadItemModel(ViewModel):
|
||||
self.view.setAction(status.name)
|
||||
else:
|
||||
self.view.setAction(status.name + '-' + desc)
|
||||
if status in _endStatus_:
|
||||
self.SIGNAL_END.emit(status)
|
||||
|
||||
|
||||
def __setErrStatus__(self, errmsg: str):
|
||||
self.status = DownloadStatus.ERROR
|
||||
self.view.setAction(self.status.name)
|
||||
self.view.setErrmsg(errmsg)
|
||||
self.__setStatus__(DownloadStatus.ERROR)
|
||||
|
||||
def __initTrack__(self, index):
|
||||
title = self.data.title
|
||||
|
||||
@@ -42,7 +42,7 @@ class MainModel(ViewModel):
|
||||
downloadImp.start()
|
||||
|
||||
def uninit(self):
|
||||
self.taskModel.stopDownloadItem()
|
||||
self.taskModel.uninit()
|
||||
downloadImp.stop()
|
||||
|
||||
def show(self, relogin: bool = False):
|
||||
|
||||
@@ -17,7 +17,7 @@ from aigpy.modelHelper import ModelBase
|
||||
|
||||
import tidal_dl
|
||||
from tidal_dl import Type
|
||||
from tidal_dl.util import API, getAudioQualityList, getVideoQualityList
|
||||
from tidal_dl.util import API, getAudioQualityList, getCurAudioQuality, getCurVideoQuality, getVideoQualityList, setCurAudioQuality, setCurVideoQuality
|
||||
from tidal_gui.view.searchView import SearchView
|
||||
from tidal_gui.viewModel.viewModel import ViewModel
|
||||
|
||||
@@ -32,12 +32,14 @@ class SearchModel(ViewModel):
|
||||
|
||||
self.view = SearchView()
|
||||
self.view.setPageIndex(1, 1)
|
||||
self.view.setTrackQualityItems(getAudioQualityList())
|
||||
self.view.setVideoQualityItems(getVideoQualityList())
|
||||
self.view.setTrackQualityItems(getAudioQualityList(), getCurAudioQuality())
|
||||
self.view.setVideoQualityItems(getVideoQualityList(), getCurVideoQuality())
|
||||
self.view.connectButton('search', self.__search__)
|
||||
self.view.connectButton('prePage', self.__searchPre__)
|
||||
self.view.connectButton('nextPage', self.__searchNext__)
|
||||
self.view.connectButton('download', self.__download__)
|
||||
self.view.connectQualityComboBox('track', self.__changeAudioQuality__)
|
||||
self.view.connectQualityComboBox('video', self.__changeVideoQuality__)
|
||||
self.view.connectTab(lambda: self.__search__(0))
|
||||
self.SIGNAL_REFRESH_VIEW.connect(self.__refresh__)
|
||||
|
||||
@@ -149,3 +151,9 @@ class SearchModel(ViewModel):
|
||||
return
|
||||
|
||||
self.SIGNAL_ADD_TASKITEM.emit(items[index])
|
||||
|
||||
def __changeAudioQuality__(self):
|
||||
setCurAudioQuality(self.view.getTrackQualityText())
|
||||
|
||||
def __changeVideoQuality__(self):
|
||||
setCurVideoQuality(self.view.getVideoQualityText())
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
@Desc :
|
||||
"""
|
||||
import _thread
|
||||
from asyncio import tasks
|
||||
from enum import Enum
|
||||
import os
|
||||
import time
|
||||
|
||||
@@ -18,7 +20,8 @@ from tidal_dl import Type
|
||||
from tidal_dl.model import Album, Track, Video, Playlist
|
||||
from tidal_dl.util import API, getArtistsNames, getBasePath, getDurationString
|
||||
from tidal_gui.view.taskItemView import TaskItemView
|
||||
from tidal_gui.viewModel.downloadItemModel import DownloadItemModel
|
||||
from tidal_gui.view.taskView import TaskStatus
|
||||
from tidal_gui.viewModel.downloadItemModel import DownloadItemModel, DownloadStatus
|
||||
from tidal_gui.viewModel.viewModel import ViewModel
|
||||
|
||||
|
||||
@@ -46,6 +49,21 @@ class TaskItemModel(ViewModel):
|
||||
|
||||
self.SIGNAL_REFRESH_VIEW.connect(self.__refresh__)
|
||||
|
||||
def getTaskStatus(self) -> TaskStatus:
|
||||
if len(self.downloadModelList) <= 0:
|
||||
return TaskStatus.Download
|
||||
|
||||
errorNum = 0
|
||||
for item in self.downloadModelList:
|
||||
if item.status in [DownloadStatus.WAIT, DownloadStatus.RUNNING, DownloadStatus.CANCEL]:
|
||||
return TaskStatus.Download
|
||||
elif item.status == DownloadStatus.ERROR:
|
||||
errorNum += 1
|
||||
|
||||
if errorNum > 0:
|
||||
return TaskStatus.Error
|
||||
return TaskStatus.Complete
|
||||
|
||||
def __refresh__(self, stype: str, obj):
|
||||
if stype == "setPic":
|
||||
self.view.setPic(obj)
|
||||
|
||||
@@ -8,10 +8,12 @@
|
||||
@Contact : yaronhuang@foxmail.com
|
||||
@Desc :
|
||||
"""
|
||||
import threading
|
||||
from PyQt5.QtCore import QTimer
|
||||
from tidal_dl.model import Album, Artist
|
||||
from tidal_gui.view.taskView import TaskView, TaskListType
|
||||
from tidal_gui.view.taskView import TaskView, TaskStatus
|
||||
from tidal_gui.viewModel.downloadItemModel import DownloadItemModel
|
||||
from tidal_gui.viewModel.taskItemModel import TaskItemModel
|
||||
from tidal_gui.viewModel.taskItemModel import TaskItemModel, TaskStatus
|
||||
from tidal_gui.viewModel.viewModel import ViewModel
|
||||
|
||||
|
||||
@@ -21,28 +23,45 @@ class TaskModel(ViewModel):
|
||||
self.view = TaskView()
|
||||
|
||||
self._listMap = {}
|
||||
for item in map(lambda typeItem: typeItem.name, TaskListType):
|
||||
for item in map(lambda typeItem: typeItem.name, TaskStatus):
|
||||
self._listMap[item] = []
|
||||
|
||||
self.test()
|
||||
self._timer = QTimer(self)
|
||||
self._timer.timeout.connect(self.__checkTaskStatus__)
|
||||
self._timer.start(3000)
|
||||
|
||||
# self.test()
|
||||
|
||||
def __checkTaskStatus__(self):
|
||||
for item in self._listMap[TaskStatus.Download.name][:]:
|
||||
status = item.getTaskStatus()
|
||||
if status == TaskStatus.Download:
|
||||
continue
|
||||
|
||||
self._listMap[TaskStatus.Download.name].remove(item)
|
||||
self.view.delItemView(TaskStatus.Download, item.view)
|
||||
|
||||
self._listMap[status.name].append(item)
|
||||
self.view.addItemView(status, item.view)
|
||||
|
||||
def uninit(self):
|
||||
self._timer.stop()
|
||||
for item in self._listMap[TaskStatus.Download.name]:
|
||||
for downItem in item.downloadModelList:
|
||||
downItem.stopDownload()
|
||||
|
||||
def addTaskItem(self, data):
|
||||
item = TaskItemModel(data)
|
||||
self._listMap[TaskListType.Download.name].append(item)
|
||||
self.view.addItemView(TaskListType.Download, item.view)
|
||||
self._listMap[TaskStatus.Download.name].append(item)
|
||||
self.view.addItemView(TaskStatus.Download, item.view)
|
||||
|
||||
def getWaitDownloadItem(self) -> DownloadItemModel:
|
||||
for item in self._listMap[TaskListType.Download.name]:
|
||||
for item in self._listMap[TaskStatus.Download.name]:
|
||||
for downItem in item.downloadModelList:
|
||||
if downItem.isInWait():
|
||||
return downItem
|
||||
return None
|
||||
|
||||
def stopDownloadItem(self):
|
||||
for item in self._listMap[TaskListType.Download.name]:
|
||||
for downItem in item.downloadModelList:
|
||||
downItem.stopDownload()
|
||||
|
||||
def test(self):
|
||||
ar = Artist()
|
||||
ar.name = 'yaron'
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
cd TIDALDL-PY
|
||||
rm -rf dist
|
||||
rm -rf build
|
||||
rm -rf exe
|
||||
rm -rf exe/tidal-dl.exe
|
||||
rm MANIFEST.in
|
||||
rm -rf tidal_dl.egg-info
|
||||
rm -rf tidal_gui.egg-info
|
||||
rm -rf tidal_dl_test.egg-info
|
||||
mkdir exe
|
||||
|
||||
# pack
|
||||
python setup.py sdist bdist_wheel
|
||||
@@ -28,13 +29,26 @@ twine upload dist/*
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cd TIDALDL-PY
|
||||
rm -rf dist
|
||||
rm -rf build
|
||||
rm -rf exe
|
||||
rm -rf build
|
||||
rm -rf exe/tidal-gui.exe
|
||||
cp -rf guiStatic.in MANIFEST.in
|
||||
rm -rf tidal_dl.egg-info
|
||||
python setup.py sdist bdist_wheel
|
||||
pip uninstall -y tidal-dl
|
||||
python setup.py install
|
||||
rm -rf tidal_gui.egg-info
|
||||
rm -rf tidal_dl_test.egg-info
|
||||
|
||||
# pack
|
||||
python setup-gui.py sdist bdist_wheel
|
||||
# creat exe file
|
||||
pyinstaller -F tidal_gui/__init__.py
|
||||
# rename exe name
|
||||
mv dist/__init__.exe exe/tidal-gui.exe
|
||||
|
||||
pip uninstall -y tidal-gui
|
||||
|
||||
# upload
|
||||
twine upload dist/*
|
||||
|
||||
Reference in New Issue
Block a user