diff --git a/README.md b/README.md index 72921e4..57aeb63 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@    [![Download PyTube Downloader](https://img.shields.io/sourceforge/dm/pytube-downloader.svg)](https://sourceforge.net/projects/pytube-downloader/files/latest/download) [![Download PyTube Downloader](https://img.shields.io/sourceforge/dw/pytube-downloader.svg)](https://sourceforge.net/projects/pytube-downloader/files/latest/download) [![Download PyTube Downloader](https://img.shields.io/sourceforge/dt/pytube-downloader.svg)](https://sourceforge.net/projects/pytube-downloader/files/latest/download) -   `v2.1.1` [Visit to Download .exe for Windows](https://sourceforge.net/p/pytube-downloader) +   `v2.1.2` [Visit to Download .exe for Windows](https://sourceforge.net/p/pytube-downloader) --- diff --git a/README_zh.md b/README_zh.md index 86b80e9..7be6609 100644 --- a/README_zh.md +++ b/README_zh.md @@ -7,7 +7,7 @@    [![Download PyTube Downloader](https://img.shields.io/sourceforge/dm/pytube-downloader.svg)](https://sourceforge.net/projects/pytube-downloader/files/latest/download) [![Download PyTube Downloader](https://img.shields.io/sourceforge/dw/pytube-downloader.svg)](https://sourceforge.net/projects/pytube-downloader/files/latest/download) [![Download PyTube Downloader](https://img.shields.io/sourceforge/dt/pytube-downloader.svg)](https://sourceforge.net/projects/pytube-downloader/files/latest/download) -   `v2.1.1` [下载适用于 Windows 的 .exe](https://sourceforge.net/p/pytube-downloader) +   `v2.1.2` [下载适用于 Windows 的 .exe](https://sourceforge.net/p/pytube-downloader) --- diff --git a/VERSION b/VERSION index 09d8c6c..a198f30 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -VERSION = '2.1.1' +VERSION = '2.1.2' diff --git a/data/general.json b/data/general.json index e12d48c..613a5ad 100644 --- a/data/general.json +++ b/data/general.json @@ -1,4 +1,5 @@ -{ +{ + "alerts": true, "automatic_download": { "quality": 0, "status": "disable" @@ -15,5 +16,5 @@ "re_download_automatically": false, "reload_automatically": false, "update_delay": 0.5, - "window_geometry": "900x500+0+0" + "window_geometry": "900x500+-7+0" } \ No newline at end of file diff --git a/data/info.json b/data/info.json index 1b3d57b..5eb6361 100644 --- a/data/info.json +++ b/data/info.json @@ -2,5 +2,5 @@ "contributors": {}, "name": "PyTube Downloader", "site": "https://github.com/Thisal-D/PyTube-Downloader", - "version": "2.1.1" + "version": "2.1.2" } \ No newline at end of file diff --git a/data/languages/en.json b/data/languages/en.json index 0e16037..c179f5e 100644 --- a/data/languages/en.json +++ b/data/languages/en.json @@ -86,5 +86,6 @@ "force_exit": "Force Exit", "minimize_to_tray": "Minimize To Tray", "reset": "Reset", - "update_alert": "A new update is available! \nVisit the official website to download the \nlatest version." + "update_alert": "A new update is available! \nVisit the official website to download the \nlatest version.", + "alerts" : "Alerts" } diff --git a/data/languages/si.json b/data/languages/si.json index f44586b..23fbca9 100644 --- a/data/languages/si.json +++ b/data/languages/si.json @@ -86,6 +86,7 @@ "force_exit": "පිටවීම", "minimize_to_tray": "ට්‍රේ එකට Minimize කරන්න", "reset": "නෑවත සකසන්න", - "update_alert": "නව අනුවාදයක් තිබේ!\nනවතම අනුවාදය බාගැනීමට කරුණාකර \nනිල වෙබ් අඩවියට පිවිසෙන්න." + "update_alert": "නව අනුවාදයක් තිබේ!\nනවතම අනුවාදය බාගැනීමට කරුණාකර \nනිල වෙබ් අඩවියට පිවිසෙන්න.", + "alerts": "දැනුම්දීම්" } \ No newline at end of file diff --git a/data/languages/zh.json b/data/languages/zh.json index 7dd537a..2efff96 100644 --- a/data/languages/zh.json +++ b/data/languages/zh.json @@ -86,5 +86,6 @@ "force_exit": "强制退出", "minimize_to_tray": "最小化到托盘", "reset": "重置", - "update_alert": "有新版本可用!\n请访问官方网站下载最新版本。" + "update_alert": "有新版本可用!\n请访问官方网站下载最新版本。", + "alerts": "警报" } diff --git a/settings/general_settings.py b/settings/general_settings.py index 06fa94d..5ad2af9 100644 --- a/settings/general_settings.py +++ b/settings/general_settings.py @@ -14,6 +14,27 @@ class GeneralSettings: backup_path = backup_dir + "\\general.json" default_download_dir = f"C:\\users\\{os.getlogin()}\\downloads\\PyTube Downloader\\" + SETTINGS = { + "automatic_download": { + "quality": 0, + "status": "disable" + }, + "create_sep_path_for_playlists": False, + "create_sep_path_for_qualities": False, + "create_sep_path_for_videos_audios": False, + "download_directory": False, + "lang_code": "en", + "language": "English", + "load_thumbnail": True, + "max_simultaneous_downloads": 1, + "max_simultaneous_loads": 1, + "re_download_automatically": False, + "reload_automatically": False, + "update_delay": 0.5, + "alerts": True, + "window_geometry": "900x500-7+0" + } + @staticmethod def initialize() -> None: """ @@ -29,14 +50,15 @@ def initialize() -> None: GeneralSettings.create_backup() if backup_exists and FileUtility.is_accessible(GeneralSettings.backup_dir): - settings = JsonUtility.read_from_file(GeneralSettings.backup_path) + GeneralSettings.settings = JsonUtility.read_from_file(GeneralSettings.backup_path) else: - settings = JsonUtility.read_from_file(GeneralSettings.file_path) - - if settings.get("download_directory") is False: - settings["download_directory"] = GeneralSettings.default_download_dir - - GeneralSettings.settings = settings + GeneralSettings.settings = JsonUtility.read_from_file(GeneralSettings.file_path) + + if not GeneralSettings.are_all_keys_present(): + GeneralSettings.add_missing_keys() + + if GeneralSettings.settings.get("download_directory") is False: + GeneralSettings.settings["download_directory"] = GeneralSettings.default_download_dir @staticmethod def save_settings() -> None: @@ -58,6 +80,29 @@ def is_backup_exists() -> bool: return True return False + @staticmethod + def are_all_keys_present() -> bool: + """ + Check if all required settings keys are present in the initialized settings. + + Returns: + bool: True if all keys exist, False otherwise. + """ + for key in GeneralSettings.SETTINGS.keys(): + if key not in GeneralSettings.settings.keys(): + return False + return True + + def add_missing_keys() -> None: + """ + Add any missing keys from the default settings to the initialized settings. + + This ensures that the settings include all required keys with their default values. + """ + for key in GeneralSettings.SETTINGS.keys(): + if key not in GeneralSettings.settings.keys(): + GeneralSettings.settings[key] = GeneralSettings.SETTINGS[key] + @staticmethod def create_backup() -> None: FileUtility.create_directory(GeneralSettings.backup_dir) diff --git a/widgets/core_widgets/setting_panel.py b/widgets/core_widgets/setting_panel.py index 6b2eeb2..961eb3d 100644 --- a/widgets/core_widgets/setting_panel.py +++ b/widgets/core_widgets/setting_panel.py @@ -77,7 +77,7 @@ def __init__( self.set_widgets_accent_color() self.set_widgets_sizes() self.place_widgets() - + def place_widgets(self) -> None: self.navigation_panel.pack(side="left", fill="y") self.vertical_line.pack(side="left", fill="y") diff --git a/widgets/play_list/downloading_play_list.py b/widgets/play_list/downloading_play_list.py index ff92379..59e8e25 100644 --- a/widgets/play_list/downloading_play_list.py +++ b/widgets/play_list/downloading_play_list.py @@ -126,7 +126,7 @@ def videos_status_track( self.downloading_videos.remove(video) if video in self.paused_videos: self.paused_videos.remove(video) - self.show_notification_for_video_state(self.failed_videos[-1]) + self.show_notification(self.failed_videos[-1]) elif state == "downloading": self.downloading_videos.append(video) if video in self.waiting_videos: @@ -146,7 +146,7 @@ def videos_status_track( elif state == "downloaded": self.downloaded_videos.append(video) self.downloading_videos.remove(video) - self.show_notification_for_video_state(self.downloaded_videos[-1]) + self.show_notification(self.downloaded_videos[-1]) # if len is 0 that means all videos are remove :D if len(self.videos) != 0: @@ -231,29 +231,30 @@ def set_downloading_completed(self): self.playlist_download_complete_callback(self) self.kill() - def show_notification_for_video_state(self, video: DownloadingVideo): - if video.download_state == "downloaded": - if self.playlist_video_count == len(self.downloaded_videos): - status_message = "Download Completed..!" - else: - status_message = "Downloading..." - elif video.download_state == "failed": - status_message = "Download Failed..!" - # Show Download completed Notification - NotificationManager.register( - playlist_title=self.playlist_title, - video_title=video.video_title, - channel_name=self.channel, - status_message=status_message, - total_videos_count=self.playlist_video_count, - completed_videos_count=len(self.downloaded_videos), - download_directory=video.download_directory, - download_file_name=video.download_file_name, - downloaded_file_size=video.bytes_downloaded, - download_mode=video.mode, - download_status=video.download_state, - thumbnail_path=video.notification_thumbnail_image_path - ) + def show_notification(self, video: DownloadingVideo): + if GeneralSettings.settings["alerts"]: + if video.download_state == "downloaded": + if self.playlist_video_count == len(self.downloaded_videos): + status_message = "Download Completed..!" + else: + status_message = "Downloading..." + elif video.download_state == "failed": + status_message = "Download Failed..!" + # Show Download completed Notification + NotificationManager.register( + playlist_title=self.playlist_title, + video_title=video.video_title, + channel_name=self.channel, + status_message=status_message, + total_videos_count=self.playlist_video_count, + completed_videos_count=len(self.downloaded_videos), + download_directory=video.download_directory, + download_file_name=video.download_file_name, + downloaded_file_size=video.bytes_downloaded, + download_mode=video.mode, + download_status=video.download_state, + thumbnail_path=video.notification_thumbnail_image_path + ) # create widgets def create_widgets(self): diff --git a/widgets/setting_panels/general_panel.py b/widgets/setting_panels/general_panel.py index 8bab5c6..eebfb35 100644 --- a/widgets/setting_panels/general_panel.py +++ b/widgets/setting_panels/general_panel.py @@ -94,6 +94,27 @@ def __init__( ) self.shortcut_keys_widgets_info.append(shortcut_keys_widgets_info_dict) + self.alerts_state_label = ctk.CTkLabel( + master=self, + text_color=AppearanceSettings.settings["settings_panel"]["text_color"] + ) + + self.dash3_label = ctk.CTkLabel( + master=self, + text=":", + text_color=AppearanceSettings.settings["settings_panel"]["text_color"] + ) + + self.alerts_state_switch_state = ctk.BooleanVar(value=None) + self.alerts_state_change_switch = ctk.CTkSwitch( + master=self, + text="", + command=self.change_alerts_state, + onvalue=True, + offvalue=False, + variable=self.alerts_state_switch_state + ) + self.settings_reset_button = ctk.CTkButton(master=self, text_color=AppearanceSettings.settings["settings_panel"]["text_color"], command=self.reset_settings) # callbacks for settings changes @@ -113,8 +134,15 @@ def __init__( def reset_settings(self): # Reset language to english and apply it self.languages_combo_box.set("English") + self.alerts_state_change_switch.select() + self.change_alerts_state() + self.apply_language("English") + def change_alerts_state(self): + GeneralSettings.settings["alerts"] = self.alerts_state_switch_state.get() + self.general_settings_change_callback() + def apply_language(self, language: str) -> None: lang_code = self.language_data[language] if lang_code != GeneralSettings.settings["lang_code"]: @@ -136,6 +164,12 @@ def set_widgets_accent_color(self): fg_color=AppearanceSettings.settings["root"]["accent_color"]["normal"], hover_color=AppearanceSettings.settings["root"]["accent_color"]["hover"] ) + + self.alerts_state_change_switch.configure( + button_color=AppearanceSettings.settings["root"]["accent_color"]["normal"], + button_hover_color=AppearanceSettings.settings["root"]["accent_color"]["hover"], + progress_color=AppearanceSettings.settings["root"]["accent_color"]["hover"] + ) def update_widgets_accent_color(self): """ @@ -170,8 +204,12 @@ def place_widgets(self): shortcut_widget_info["key_frame"].grid(row=i, column=2, pady=(4 * scale, 0), sticky="w") for button in shortcut_widget_info["buttons"]: button.pack(side="left", padx=(2 * scale, 0)) - - self.settings_reset_button.grid(row=2, column=2, padx=(100, 0), pady=(pady, 0), sticky="e") + + self.alerts_state_label.grid(row=2, column=0, padx=(100, 0), pady=(pady, 0), sticky="w") + self.dash3_label.grid(row=2, column=1, padx=(30, 30), pady=(pady, 0), sticky="w") + self.alerts_state_change_switch.grid(row=2, column=2, padx=(0, 0), pady=(pady, 0), sticky="w") + + self.settings_reset_button.grid(row=3, column=2, padx=(100, 0), pady=(pady, 0), sticky="s") def set_widgets_sizes(self): scale = AppearanceSettings.settings["scale_r"] @@ -183,6 +221,8 @@ def set_widgets_sizes(self): for button in shortcut_widget_info["buttons"]: button.configure(width=1, height=24 * scale) + self.alerts_state_change_switch.configure(switch_width=36 * scale, switch_height=18 * scale) + self.settings_reset_button.configure(width=80*scale, height=24 * scale) def set_widgets_texts(self): @@ -196,6 +236,10 @@ def set_widgets_texts(self): text=LanguageManager.data["reset"] ) + self.alerts_state_label.configure( + text=LanguageManager.data["alerts"] + ) + def update_widgets_text(self): self.set_widgets_texts() @@ -207,7 +251,8 @@ def set_widgets_fonts(self): self.dash1_label.configure(font=title_font) self.shortcut_label.configure(font=title_font) self.dash2_label.configure(font=title_font) - + self.alerts_state_label.configure(font=title_font) + value_font = ("Segoe UI", 13 * scale, "normal") self.languages_combo_box.configure(font=value_font, dropdown_font=value_font) @@ -230,3 +275,7 @@ def set_widgets_values(self): set values for widgets using saved settings. """ self.languages_combo_box.set(GeneralSettings.settings["language"]) + + if GeneralSettings.settings["alerts"]: + self.alerts_state_change_switch.select() + self.alerts_state_switch_state.set(True) diff --git a/widgets/video/downloading_video.py b/widgets/video/downloading_video.py index e6f512d..78a6739 100644 --- a/widgets/video/downloading_video.py +++ b/widgets/video/downloading_video.py @@ -344,7 +344,7 @@ def set_downloading_failed(self): anchor="w", relx=1, x=-80 * AppearanceSettings.settings["scale_r"]) - + if self.mode == "video": self.show_notification() @@ -381,24 +381,25 @@ def set_downloading_completed(self): self.kill() def show_notification(self): - if self.download_state == "downloaded": - status_message = "Download Completed..!" - else: - status_message = "Download Failed..!" - # Show Download completed Notification - NotificationManager.register( - video_title=self.video_title, - channel_name=self.channel, - status_message=status_message, - download_type="{}/{}".format(self.download_type, self.download_quality), - file_size=self.file_size, - download_directory=self.download_directory, - download_file_name=self.download_file_name, - downloaded_file_size=self.bytes_downloaded, - download_mode=self.mode, - download_status=self.download_state, - thumbnail_path=self.notification_thumbnail_image_path - ) + if GeneralSettings.settings["alerts"]: + if self.download_state == "downloaded": + status_message = "Download Completed..!" + else: + status_message = "Download Failed..!" + # Show Download completed Notification + NotificationManager.register( + video_title=self.video_title, + channel_name=self.channel, + status_message=status_message, + download_type="{}/{}".format(self.download_type, self.download_quality), + file_size=self.file_size, + download_directory=self.download_directory, + download_file_name=self.download_file_name, + downloaded_file_size=self.bytes_downloaded, + download_mode=self.mode, + download_status=self.download_state, + thumbnail_path=self.notification_thumbnail_image_path + ) # create widgets def create_widgets(self):