Skip to content

Commit 026cf54

Browse files
author
Kyle-Myre
committed
2 parents 296865a + 158c5fb commit 026cf54

12 files changed

+176
-138
lines changed

.github/workflows/pyinstaller.yaml

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ jobs:
2626
- name: Build with PyInstaller
2727
run: |
2828
pyinstaller --onefile --name Dandilion --add-data "app:app" --icon=assets/icon.ico main.py
29+
- name: List dist directory contents
30+
run: ls -R dist
2931
- name: Upload artifact
3032
uses: actions/upload-artifact@v4
3133
with:
3234
name: Dandilion-${{ matrix.os }}
33-
path: dist/Dandilion
35+
path: dist/Dandilion

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# 🌼 Dandilion 🌼
1+
# 🌼 Dandilion 🌼 [UNDER REWORK]
22

33
[![Python](https://img.shields.io/badge/Python-3776AB?logo=python&logoColor=fff)](#) [![Bash](https://img.shields.io/badge/Bash-4EAA25?logo=gnubash&logoColor=fff)](#) [![XML](https://img.shields.io/badge/XML-767C52?logo=xml&logoColor=fff)](#) [![YouTube](https://img.shields.io/badge/YouTube-%23FF0000.svg?logo=YouTube&logoColor=white)](#) [![GitHub Copilot](https://img.shields.io/badge/GitHub%20Copilot-000?logo=githubcopilot&logoColor=fff)](#)
44

app/__init__.py

+135-93
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,150 @@
1-
from app.errors.URLEmptyException import URLEmptyException
2-
from app.services.DownloadService import DownloadService
3-
from app.settings.settings import Settings
4-
from app.widgets.about import Ui_About
5-
from app.widgets.app import Ui_Dandilion
6-
from PySide6.QtGui import QDesktopServices
7-
from PySide6.QtCore import QThread
8-
from PySide6.QtCore import QObject
9-
from PySide6.QtCore import Signal
10-
from PySide6.QtWidgets import QApplication
11-
from PySide6.QtWidgets import QMessageBox
12-
from PySide6.QtWidgets import QMainWindow
13-
from PySide6.QtWidgets import QWidget
14-
from PySide6.QtCore import QUrl
1+
from app.handlers.URLEmptyException import URLEmptyException
2+
from app.services.DownloadService import DownloadService
3+
from app.settings.settings import Settings
4+
from app.widgets.about import AboutWidget
5+
from app.widgets.app import MainWidget
6+
7+
from PySide6.QtGui import QDesktopServices
8+
from PySide6.QtCore import QThread
9+
from PySide6.QtCore import QObject
10+
from PySide6.QtCore import Signal
11+
from PySide6.QtWidgets import QApplication
12+
from PySide6.QtWidgets import QMessageBox
13+
from PySide6.QtWidgets import QMainWindow
14+
from PySide6.QtWidgets import QWidget
15+
from PySide6.QtCore import QUrl
1516
import sys
1617

17-
class DownloadWorker(QObject):
18-
finished = Signal()
19-
error_occurred = Signal(str)
18+
# class DownloadWorker(QObject):
2019

21-
def __init__(self, url, path, file_type, download_service):
22-
super().__init__()
23-
self.url = url
24-
self.path = path
25-
self.file_type = file_type
26-
self.download_service = download_service
20+
# finished = Signal()
21+
# error_occurred = Signal(str)
22+
23+
# def __init__(self, url, path, file_type, download_service):
24+
# super().__init__()
25+
# self.url = url
26+
# self.path = path
27+
# self.file_type = file_type
28+
# self.download_service = download_service
29+
30+
# def run(self):
31+
# try:
32+
# self.download_service.download(self.url, self.path, self.file_type)
33+
# except Exception as e:
34+
# self.error_occurred.emit(str(e))
35+
# finally:
36+
# self.finished.emit()
2737

28-
def run(self):
29-
try:
30-
self.download_service.download(self.url, self.path, self.file_type)
31-
except Exception as e:
32-
self.error_occurred.emit(str(e))
33-
finally:
34-
self.finished.emit()
35-
36-
class Application:
37-
"""
38-
The Application class initializes and sets up the main application, including
39-
the main window, about window, and settings window. It also manages the download
40-
service and its associated thread.
41-
"""
42-
main_widget = Ui_Dandilion()
43-
about_widget = Ui_About()
44-
settings_config = Settings()
45-
def __init__(self):
46-
"""
47-
Initializes the Application class by setting up the QApplication, main window,
48-
about window, and settings window. It also configures the application style
49-
and sets up the UI components and services.
50-
"""
51-
# Injecting
52-
self.app = QApplication(sys.argv)
53-
self.main_window = QMainWindow()
54-
self.about_window = QWidget()
55-
self.settings_window = QWidget()
56-
self.app.setStyle(self.settings_config.config['theme'])
57-
# Setting Up
58-
self.main_widget.setupUi(self.main_window)
59-
self.about_widget.setupUi(self.about_window)
60-
self.main_window.setFixedSize(836, 324)
61-
self.about_window.setFixedSize(400, 125)
62-
# Services
63-
self.download_service = DownloadService(
64-
self.main_widget.DownloadProgressBar, self.main_widget.OutputAreaBox
65-
)
66-
self.download_thread = None # Initialize as None
67-
self.set_actions()
6838

39+
class ApplicationContext:
40+
41+
__main_widget :MainWidget
42+
__about_widget :AboutWidget
43+
__download_service :DownloadService
44+
__version_service :str
45+
46+
@property
47+
def __app(self):
48+
return QApplication(sys.argv)
49+
50+
def __init__(self , main_widget:MainWidget,about_widget:AboutWidget,download_service:DownloadService):
51+
52+
self.__main_widget = main_widget
53+
self.__about_widget = about_widget
54+
self.__download_service = download_service
55+
56+
self.__set_up()
57+
58+
def __set_up(self):
59+
# self.__app.setStyle(self.__settings_config.config['theme']);
60+
self.__main_widget.setupUi(QMainWindow().setFixedSize(836, 324));
61+
self.__about_widget.setupUi(QWidget().setFixedSize(400, 125));
62+
63+
def run(self):
64+
...
65+
6966
def start_download(self):
67+
...
68+
69+
70+
71+
72+
7073

71-
if self.main_widget.UrlEntry.text() == "":
72-
self.show_error_message("Empty URL Warning", "Please provide a URL.")
73-
return
74+
75+
76+
77+
78+
79+
80+
81+
82+
83+
84+
85+
def load_config(self):
86+
...
87+
88+
# """
89+
# Initializes the Application class by setting up the QApplication, main window,
90+
# about window, and settings window. It also configures the application style
91+
# and sets up the UI components and services.
92+
# """
93+
# # Injecting
94+
# self.app = QApplication(sys.argv)
95+
# self.main_window = QMainWindow()
96+
# self.about_window = QWidget()
97+
# self.settings_window = QWidget()
98+
# self.app.setStyle(self.settings_config.config['theme'])
99+
# # Setting Up
100+
# self.main_widget.setupUi(self.main_window)
101+
# self.about_widget.setupUi(self.about_window)
102+
# self.main_window.setFixedSize(836, 324)
103+
# self.about_window.setFixedSize(400, 125)
104+
# # Services
105+
# self.download_service = DownloadService(
106+
# self.main_widget.DownloadProgressBar, self.main_widget.OutputAreaBox
107+
# )
108+
# self.download_thread = None # Initialize as None
109+
# self.set_actions()
110+
111+
# def start_download(self):
112+
113+
# if self.main_widget.UrlEntry.text() == "":
114+
# self.show_error_message("Empty URL Warning", "Please provide a URL.")
115+
# return
74116

75-
self.main_widget.OutputAreaBox.insertPlainText("Starting download...\n")
117+
# self.main_widget.OutputAreaBox.insertPlainText("Starting download...\n")
76118

77-
url = self.main_widget.UrlEntry.text()
78-
path = self.settings_config.config['path']
79-
file_type = self.main_widget.TypeComboBox.currentText()
119+
# url = self.main_widget.UrlEntry.text()
120+
# path = self.settings_config.config['path']
121+
# file_type = self.main_widget.TypeComboBox.currentText()
80122

81-
# Create and set up worker thread
82-
self.download_thread = QThread()
83-
self.download_worker = DownloadWorker(url, path, file_type, self.download_service)
84-
self.download_worker.moveToThread(self.download_thread)
123+
# # Create and set up worker thread
124+
# self.download_thread = QThread()
125+
# self.download_worker = DownloadWorker(url, path, file_type, self.download_service)
126+
# self.download_worker.moveToThread(self.download_thread)
85127

86-
# Connect signals
87-
self.download_thread.started.connect(self.download_worker.run)
88-
self.download_worker.finished.connect(self.download_thread.quit)
89-
self.download_worker.finished.connect(self.download_worker.deleteLater)
90-
self.download_thread.finished.connect(self.download_thread.deleteLater)
91-
self.download_worker.error_occurred.connect(self.show_error_message)
128+
# # Connect signals
129+
# self.download_thread.started.connect(self.download_worker.run)
130+
# self.download_worker.finished.connect(self.download_thread.quit)
131+
# self.download_worker.finished.connect(self.download_worker.deleteLater)
132+
# self.download_thread.finished.connect(self.download_thread.deleteLater)
133+
# self.download_worker.error_occurred.connect(self.show_error_message)
92134

93-
# Start the thread
94-
self.download_thread.start()
135+
# # Start the thread
136+
# self.download_thread.start()
95137

96-
def show_error_message(self, title, message):
97-
msg = QMessageBox()
98-
msg.critical(self.main_window, title, message)
138+
# def show_error_message(self, title, message):
139+
# msg = QMessageBox()
140+
# msg.critical(self.main_window, title, message)
99141

100-
def set_actions(self):
101-
url = QUrl('https://github.com/Kyle-Myre')
102-
self.main_widget.DownloadButton.clicked.connect(self.start_download)
103-
self.main_widget.WikiButton.clicked.connect(self.about_window.show)
104-
self.main_widget.GithubButton.clicked.connect(lambda: QDesktopServices.openUrl(url))
142+
# def set_actions(self):
143+
# url = QUrl('https://github.com/Kyle-Myre')
144+
# self.main_widget.DownloadButton.clicked.connect(self.start_download)
145+
# self.main_widget.WikiButton.clicked.connect(self.about_window.show)
146+
# self.main_widget.GithubButton.clicked.connect(lambda: QDesktopServices.openUrl(url))
105147

106-
def run(self):
107-
self.main_window.show()
108-
sys.exit(self.app.exec())
148+
# def run(self):
149+
# self.main_window.show()
150+
# sys.exit(self.app.exec())

app/app.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from app import ApplicationContext
2+
3+
4+
class DandilionApplication(object):
5+
"""
6+
DandilionApplication is the main entry point for the Dandilion application.
7+
8+
This class initializes and runs the application by creating an instance of the Application class
9+
and calling its run method.
10+
"""
11+
def __init__(self):
12+
self.__context = ApplicationContext()
13+
14+
def run(self):
15+
self.__context.run()
File renamed without changes.
File renamed without changes.

app/services/DownloadService.py

+15-30
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,29 @@
1-
from .DownloadServiceAbstract import DownloadServiceAbstract
21
from PySide6.QtWidgets import QProgressBar
32
from PySide6.QtWidgets import QPlainTextEdit
43
from yt_dlp.utils import DownloadError
54
from yt_dlp import YoutubeDL
65

7-
class DownloadService(DownloadServiceAbstract):
8-
6+
7+
class DownloadService(object):
8+
99
def __init__(self , progress_bar:QProgressBar , output_text:QPlainTextEdit):
1010
super().__init__()
1111
self.progress_bar = progress_bar
1212
self.output_text = output_text
1313

1414
def on_progress(self , info_dict:dict):
15-
16-
file = info_dict.get('filname', 'Unknown')
17-
downloaded = info_dict.get('downloaded_bytes', 0)
18-
total = info_dict.get('total_bytes', 0)
19-
if total:
20-
percent = int((downloaded / total) * 100)
21-
self.progress_bar.setValue(percent)
22-
self.output_text.insertPlainText(f"Downloading {file}: {downloaded}/{total} bytes ({percent:.2f}%)\n")
23-
24-
def download(self , url:str , path:str , type:str):
25-
"""Downloads a video from youtube and extracts its audio
26-
into an mp3 file, saving it to the given path.
2715

28-
Args:
29-
url (str): The url of the video to download.
30-
path (str): The path where the mp3 file will be saved.
16+
self.__file = info_dict.get('filname', 'Unknown')
17+
self.__downloaded = info_dict.get('downloaded_bytes', 0)
18+
self.__total = info_dict.get('total_bytes', 0)
3119

32-
Returns:
33-
A dictionary containing either {"file": str} or {"error": str}.
34-
The "file" key is present when the download is successful, and
35-
contains the path of the saved mp3 file.
36-
The "error" key is present when the download fails, and contains
37-
the error message as a string.
38-
"""
20+
if self.__total:
21+
self.__percent = int((self.__downloaded / self.__total) * 100)
22+
self.progress_bar.setValue(self.__percent)
23+
self.output = f"Downloading {self.__file}: {self.__downloaded}/{self.__total} bytes ({percent:.2f}%)\n"
24+
self.output_text.insertPlainText(self.output)
25+
26+
def download(self , url:str , path:str , type:str):
3927
try:
4028
self.ydl_opts = {
4129
"outtmpl": f"{path}/%(id)s.%(ext)s",
@@ -45,17 +33,14 @@ def download(self , url:str , path:str , type:str):
4533
if type.lower() in ["mp3", "ogg", "wav"]:
4634
self.ydl_opts["extractaudio"] = True
4735
self.ydl_opts["audioformat"] = type
48-
self.ydl_opts["postprocessors"] = [
49-
{
36+
self.ydl_opts["postprocessors"] = [{
5037
"key": "FFmpegExtractAudio",
5138
"preferredcodec": type,
5239
"preferredquality": "0",
53-
}
54-
]
40+
}]
5541
elif type.lower() in ["mp4"]:
5642
self.ydl_opts["format"] = "best"
5743

58-
# Use YoutubeDL to process the download
5944
with YoutubeDL(self.ydl_opts) as youtubeClient:
6045
streamed_file = youtubeClient.download([url])
6146

app/services/DownloadServiceAbstract.py

-7
This file was deleted.

app/services/VersionService.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@
1010
original_filename="Dandilion.exe",
1111
product_name="Dandilion",
1212
translations=[0, 1200]
13-
)
13+
)
14+
15+

app/widgets/about.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
import app.resources.assets_rc as assets_rc
2222

23-
class Ui_About(object):
23+
class AboutWidget(object):
2424
def setupUi(self, About):
2525
if not About.objectName():
2626
About.setObjectName(u"About")

app/widgets/app.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
import app.resources.assets_rc as assets_rc
6363

6464

65-
class Ui_Dandilion(object):
65+
class MainWidget(object):
6666
def setupUi(self, Dandilion):
6767
if not Dandilion.objectName():
6868
Dandilion.setObjectName("Dandilion")

0 commit comments

Comments
 (0)