From bf85907ddb4780abf88852bfc1975bfa2e2c7055 Mon Sep 17 00:00:00 2001 From: Rohan Kishore <109947257+rohankishore@users.noreply.github.com> Date: Sun, 22 Oct 2023 10:42:33 +0530 Subject: [PATCH 01/14] #1 Added requirements --- requirements.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..5697f5d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,10 @@ +certifi==2023.7.22 +charset-normalizer==3.3.0 +darkdetect==0.7.1 +idna==3.4 +PyQt6==6.5.3 +PyQt6-Qt6==6.5.3 +PyQt6-sip==13.6.0 +pyqtdarktheme==2.1.0 +requests==2.31.0 +urllib3==2.0.6 From b1da0c6e5e1f2dd349fbdfe8e7b1039600a97d92 Mon Sep 17 00:00:00 2001 From: Rohan Kishore <109947257+rohankishore@users.noreply.github.com> Date: Sun, 22 Oct 2023 11:37:19 +0530 Subject: [PATCH 02/14] #1 error handling changes - Added error handling in some areas - Fixed the issue where the whole app crashed when you click "Write to JSON" (QFileDialog wasn't imported) - some basic refactoring here and there --- src/json_operations.py | 66 +++++++++++------------- src/main.py | 113 +++++++++++++++++++++++++---------------- src/search.py | 66 +++++++++++++----------- 3 files changed, 136 insertions(+), 109 deletions(-) diff --git a/src/json_operations.py b/src/json_operations.py index 95436e2..ee7b91d 100644 --- a/src/json_operations.py +++ b/src/json_operations.py @@ -1,54 +1,47 @@ -import os.path -import requests import json +from PyQt6.QtWidgets import QFileDialog, QMessageBox -def json_to_tabular(self, iad=False): + +def json_to_tabular(self, include_all_details=False): # Accessing information in the JSON data - result = self.a['result'] + result = self.a["result"] formatted_data = "" for entry in result: - anilist = entry['anilist'] - filename = entry['filename'] - episode = entry['episode'] - from_time = entry['from'] - to_time = entry['to'] - similarity = entry['similarity'] * 100 - video_url = entry['video'] - image_url = entry['image'] + anilist = entry["anilist"] + filename = entry["filename"] + episode = entry["episode"] + from_time = entry["from"] + to_time = entry["to"] + similarity = entry["similarity"] * 100 + video_url = entry["video"] + image_url = entry["image"] # Format the data with labels and insert into the QTextEdit widget - if iad is False: - formatted_data += ( - f"Filename: {filename}\n" - f"Episode: {episode}\n" - f"From: {from_time}\n" - f"To: {to_time}\n" - f"Similarity: {similarity:.2f}%\n\n" - ) - else: + formatted_data += ( + f"Filename: {filename}\n" + f"Episode: {episode}\n" + f"From: {from_time}\n" + f"To: {to_time}\n" + f"Similarity: {similarity:.2f}%\n\n" + ) + if include_all_details: formatted_data += ( - f"Filename: {filename}\n" - f"Episode: {episode}\n" - f"From: {from_time}\n" - f"To: {to_time}\n" - f"Similarity: {similarity:.2f}%\n\n" - f"From: {from_time}\n" - f"To: {to_time}\n" f"Anilist: {anilist}\n" f"Video URL: {video_url}\n" f"Image URL: {image_url}\n" - ) self.textbox.setPlainText(formatted_data) def write_to_json(self): - # Open a file dialog to select a file to write to - options = QFileDialog.Options() - file_path, _ = QFileDialog.getSaveFileName(self, "Save JSON File", "", "JSON Files (*.json);;All Files (*)", - options=options) + file_path, _ = QFileDialog.getSaveFileName( + self, + "Save JSON File", + "", + "JSON Files (*.json);;All Files (*)", + ) if file_path: try: @@ -57,8 +50,9 @@ def write_to_json(self): json.dump(self.a, file) # Inform the user that the file has been saved - QMessageBox.information(self, "File Saved", "The file has been saved successfully.") - except Exception as e: + QMessageBox.information( + self, "File Saved", "The file has been saved successfully." + ) + except FileNotFoundError or PermissionError as e: # Handle any exceptions that may occur QMessageBox.critical(self, "Error", f"An error occurred: {str(e)}") - diff --git a/src/main.py b/src/main.py index bebc30c..ccdf5b5 100644 --- a/src/main.py +++ b/src/main.py @@ -15,18 +15,26 @@ def __init__(self): self.setWindowTitle("AnimeSnap") self.setGeometry(100, 100, 450, 150) + # Create a stacked widget to manage different screens + self.stacked_widget = QStackedWidget(self) + self.setCentralWidget(self.stacked_widget) + + # Create the main menu widget + self.main_menu_widget = QWidget(self) + self.stacked_widget.addWidget(self.main_menu_widget) + self.img_path = "" self.img_url = "" self.anilist_id = "" self.ctheme = "dark" - central_widget = QWidget() + central_widget = QWidget(self) self.setCentralWidget(central_widget) layout = QVBoxLayout() central_widget.setLayout(layout) - self.buttons_frame = QWidget() + self.buttons_frame = QWidget(self) layout.addWidget(self.buttons_frame) # Create a horizontal layout @@ -55,7 +63,6 @@ def __init__(self): button_layout.addWidget(self.img_url_entry) - open_image_icon = QIcon("icons/folder.png") self.open_image_button = QPushButton(self) self.open_image_button.clicked.connect(self.open_image) @@ -64,7 +71,7 @@ def __init__(self): self.open_image_button.setFixedSize(28, 28) button_layout.addWidget(self.open_image_button) - layout.addLayout(button_layout)# Add the button layout to the main layout + layout.addLayout(button_layout) # Add the button layout to the main layout layout.addWidget(self.file_path_label) layout.addWidget(QLabel("")) @@ -82,17 +89,23 @@ def __init__(self): layout.addWidget(QLabel("Anilist Anime ID [OPTIONAL] [https://anilist.co/]")) self.anilist_entry = QLineEdit(self) - self.anilist_entry.setPlaceholderText("Use this if you know what anime it is and you just need the scene details") + self.anilist_entry.setPlaceholderText( + "Use this if you know what anime it is and you just need the scene details" + ) layout.addWidget(self.anilist_entry) - search_button = QPushButton("Search") search_button.clicked.connect(self.onClickSearch) layout.addWidget(search_button) def open_image(self): - #options = QFileDialog.Options() - file_path, _ = QFileDialog.getOpenFileName(self, "Open Image to Search", "", "Image Files (*.jpg *.png *.bmp);;All Files (*)") + # options = QFileDialog.Options() + file_path, _ = QFileDialog.getOpenFileName( + self, + "Open Image to Search", + "", + "Image Files (*.jpg *.png *.bmp);;All Files (*)", + ) if file_path: self.img_path = file_path @@ -101,7 +114,7 @@ def open_image(self): def returnToMenu(self): self.stacked_widget.setCurrentWidget(self.main_menu_widget) self.img_path = "" - self.main_menu_widget.file_path_label.setPlainText("") + self.file_path_label.setText("") # Use self.file_path_label instead of self.main_menu_widget.file_path_label def onClickThemeIcon(self): if self.ctheme == "dark": @@ -114,48 +127,60 @@ def onClickThemeIcon(self): def onThemeIconVisibilityChanged(self): if self.ctheme == "dark": - self.themes_button.setIcon(QIcon('icons/dark.png')) + self.themes_button.setIcon(QIcon("icons/dark.png")) else: - self.themes_button.setIcon(QIcon('icons/light.png')) + self.themes_button.setIcon(QIcon("icons/light.png")) def onClickSearch(self): - # Clear the layout - while self.layout().count(): - item = self.layout().takeAt(0) - widget = item.widget() - if widget is not None: - widget.deleteLater() - self.img_url = self.img_url_entry.text() anilist_id = self.anilist_entry.text() - anilist_status = "" - rbb_status = "" - iad_status = "" - - if self.checkbox_iad.isChecked(): - iad_status = True - else: - iad_status = False - - if self.checkbox_rbb.isChecked(): - rbb_status = True - else: - rbb_status = False - - if anilist_id == "": - anilist_status = None - else: - anilist_status = anilist_id - - if self.img_url == "": - search.search_img(self, anilist_info=anilist_status, rbb=rbb_status) - else: - search.search_url(self) + iad_status = self.checkbox_iad.isChecked() + rbb_status = self.checkbox_rbb.isChecked() + anilist_status = anilist_id if anilist_id else None + + if self.img_url or self.img_path != "": + while self.layout().count(): + item = self.layout().takeAt(0) + widget = item.widget() + if widget is not None: + widget.deleteLater() + + if self.checkbox_iad.isChecked(): + iad_status = True + else: + iad_status = False + + if self.checkbox_rbb.isChecked(): + rbb_status = True + else: + rbb_status = False + + if anilist_id == "": + anilist_status = None + else: + anilist_status = anilist_id + + if self.img_url == "": + search.search_img(self, anilist_info=anilist_status, rbb=rbb_status) + else: + search.search_url(self) + + if iad_status is True: + json_operations.json_to_tabular(self, include_all_details=True) + else: + json_operations.json_to_tabular(self, include_all_details=False) - if iad_status is True: - json_operations.json_to_tabular(self, iad=True) else: - json_operations.json_to_tabular(self, iad=False) + dlg = QMessageBox(self) + dlg.setWindowTitle("Error") + dlg.setText("Select any Image or Enter any URL to search") + dlg.setStandardButtons(QMessageBox.StandardButton.Ok) + button = dlg.exec() + + if button == QMessageBox.StandardButton.Ok: + pass + else: + pass if __name__ == "__main__": diff --git a/src/search.py b/src/search.py index f474679..9d8d5e2 100644 --- a/src/search.py +++ b/src/search.py @@ -1,32 +1,34 @@ -import os.path -import json_operations -import requests import urllib -import json + +import requests from PyQt6.QtWidgets import QVBoxLayout, QTextEdit, QPushButton, QWidget +import json_operations + -def search_img(self, anilist_info = None, rbb=False): +def search_img(self, anilist_info=None, rbb=False): self.setGeometry(100, 100, 750, 800) self.a = "" if anilist_info is None: - self.a = requests.post("https://api.trace.moe/search", - files={"image": open(f"{self.img_path}", "rb")} - ).json() + self.a = requests.post( + "https://api.trace.moe/search", + files={"image": open(f"{self.img_path}", "rb")}, + ).json() else: if rbb is False: url = f"https://api.trace.moe/search?anilistID={anilist_info}&url=" + "{}" - self.a = requests.get(url - .format(urllib.parse.quote_plus(f"{self.img_path}"))).json() + self.a = requests.get( + url.format(urllib.parse.quote_plus(f"{self.img_path}")) + ).json() else: - url = f"https://api.trace.moe/search?anilistID={anilist_info}&url="+"{}" - self.a = requests.get(url - .format(urllib.parse.quote_plus(f"{self.img_path}"))).json() - + url = f"https://api.trace.moe/search?anilistID={anilist_info}&url=" + "{}" + self.a = requests.get( + url.format(urllib.parse.quote_plus(f"{self.img_path}")) + ).json() self.textbox = QTextEdit() - self.textbox.setPlainText(str(self.a)+ "\n" + "\n") + self.textbox.setPlainText(str(self.a) + "\n" + "\n") self.textbox.setReadOnly(True) layout = QVBoxLayout() @@ -44,33 +46,39 @@ def search_img(self, anilist_info = None, rbb=False): central_widget.setLayout(layout) self.setCentralWidget(central_widget) -def search_url(self, anilist_info = None, rbb = False): + +def search_url(self, anilist_info=None, rbb=False): self.setGeometry(100, 100, 750, 800) self.a = "" if anilist_info is None: - self.a = requests.post("https://api.trace.moe/search", - files={"image": open(f"{self.img_url}", "rb")} - ).json() + self.a = requests.post( + "https://api.trace.moe/search", + files={"image": open(f"{self.img_url}", "rb")}, + ).json() else: if rbb is False: - url = f"https://api.trace.moe/search?anilistID={anilist_info}&url="+"{}" - self.a = requests.get(url - .format(urllib.parse.quote_plus(f"{self.img_url}"))).json() + url = f"https://api.trace.moe/search?anilistID={anilist_info}&url=" + "{}" + self.a = requests.get( + url.format(urllib.parse.quote_plus(f"{self.img_url}")) + ).json() else: - url = "https://api.trace.moe/search?anilistID"+str(stranilist_info)+"&url="+"{}" - self.a = requests.get(url - .format(urllib.parse.quote_plus(f"{self.img_url}"))).json() + url = ( + "https://api.trace.moe/search?anilistID" + + str(anilist_info) + + "&url=" + + "{}" + ) + self.a = requests.get( + url.format(urllib.parse.quote_plus(f"{self.img_url}")) + ).json() self.textbox = QTextEdit() - self.textbox.setPlainText(str(self.a)+ "\n" + "\n") + self.textbox.setPlainText(str(self.a) + "\n" + "\n") self.textbox.setReadOnly(True) layout = QVBoxLayout() layout.addWidget(self.textbox) - - central_widget = QWidget() central_widget.setLayout(layout) self.setCentralWidget(central_widget) - From e225669a7742ca82ad1f0eb6f308ca752c71c5a4 Mon Sep 17 00:00:00 2001 From: Rohan Kishore <109947257+rohankishore@users.noreply.github.com> Date: Thu, 9 Nov 2023 16:21:48 +0530 Subject: [PATCH 03/14] Create FUNDING.yml --- FUNDING.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 FUNDING.yml diff --git a/FUNDING.yml b/FUNDING.yml new file mode 100644 index 0000000..438aa70 --- /dev/null +++ b/FUNDING.yml @@ -0,0 +1,13 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: 'https://ko-fi.com/rohankishore' +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +custom: From 9a4d11a86de1c4ec26d3de82e1901d128e35e19b Mon Sep 17 00:00:00 2001 From: Rohan Kishore Date: Sun, 18 Aug 2024 00:24:36 +0530 Subject: [PATCH 04/14] fluent design init --- src/main.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main.py b/src/main.py index ccdf5b5..58ae0e4 100644 --- a/src/main.py +++ b/src/main.py @@ -2,6 +2,10 @@ import os import json_operations import search +from qfluentwidgets import * +from qfluentwidgets import FluentIcon as FIF +from qframelesswindow import * + import qdarktheme from PyQt6.QtCore import * from PyQt6.QtGui import * From 7672ff5ebdb5f5a42ecb9c1e76ca130bcd23644a Mon Sep 17 00:00:00 2001 From: Rohan Kishore Date: Sun, 18 Aug 2024 00:36:27 +0530 Subject: [PATCH 05/14] fluent design init --- .idea/.gitignore | 3 + .idea/AnimeSnap.iml | 8 + .idea/inspectionProfiles/Project_Default.xml | 96 ++++++++ .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + src/AnimeSearch.py | 185 ++++++++++++++ src/main.py | 228 +++++------------- 9 files changed, 373 insertions(+), 171 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/AnimeSnap.iml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 src/AnimeSearch.py diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/AnimeSnap.iml b/.idea/AnimeSnap.iml new file mode 100644 index 0000000..dee4210 --- /dev/null +++ b/.idea/AnimeSnap.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..fd3e62a --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,96 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..44a3ee0 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..b1f9072 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/AnimeSearch.py b/src/AnimeSearch.py new file mode 100644 index 0000000..1a7c917 --- /dev/null +++ b/src/AnimeSearch.py @@ -0,0 +1,185 @@ +import sys +import os +import json_operations +import search +from qfluentwidgets import * +from qfluentwidgets import FluentIcon as FIF +from qframelesswindow import * + +import qdarktheme +from PyQt6.QtCore import * +from PyQt6.QtGui import * +from PyQt6.QtWidgets import * + + +class App(QWidget): + def __init__(self): + super().__init__() + + self.setObjectName("AnimeSnap") + self.setGeometry(100, 100, 450, 150) + + # Create a stacked widget to manage different screens + self.stacked_widget = QStackedWidget(self) + + # Create the main menu widget + self.main_menu_widget = QWidget(self) + self.stacked_widget.addWidget(self.main_menu_widget) + + self.img_path = "" + self.img_url = "" + self.anilist_id = "" + self.ctheme = "dark" + + layout = QVBoxLayout(self) + layout.addStretch() + self.setLayout(layout) + + self.buttons_frame = QWidget(self) + layout.addWidget(self.buttons_frame) + + # Create a horizontal layout + top_layout = QHBoxLayout() + button_layout = QHBoxLayout() + checkbox_layout = QHBoxLayout() + + theme_icon = QIcon("icons/dark.png") + self.themes_button = QPushButton(self) + self.themes_button.setIconSize(QSize(23, 23)) + self.themes_button.clicked.connect(self.onClickThemeIcon) + self.themes_button.setIcon(theme_icon) + self.themes_button.setText("") + self.themes_button.setFixedSize(23, 23) + top_layout.addStretch() + top_layout.addWidget(self.themes_button) + + layout.addLayout(top_layout) + + layout.addWidget(QLabel("")) + + self.img_url_entry = QLineEdit(self) + self.img_url_entry.setPlaceholderText("Enter image URL or Upload an image") + + self.file_path_label = QLabel("") + + button_layout.addWidget(self.img_url_entry) + + open_image_icon = QIcon("icons/folder.png") + self.open_image_button = QPushButton(self) + self.open_image_button.clicked.connect(self.open_image) + self.open_image_button.setIcon(open_image_icon) + self.open_image_button.setIconSize(QSize(23, 23)) + self.open_image_button.setFixedSize(28, 28) + button_layout.addWidget(self.open_image_button) + + layout.addLayout(button_layout) # Add the button layout to the main layout + layout.addWidget(self.file_path_label) + + layout.addWidget(QLabel("")) + + layout.addLayout(checkbox_layout) # Add the checkbox layout to the main layout + + self.checkbox_rbb = QCheckBox("Remove Black Borders") + checkbox_layout.addWidget(self.checkbox_rbb) + + self.checkbox_iad = QCheckBox("Include All Details") + checkbox_layout.addWidget(self.checkbox_iad) + + layout.addWidget(QLabel("")) + + layout.addWidget(QLabel("Anilist Anime ID [OPTIONAL] [https://anilist.co/]")) + + self.anilist_entry = QLineEdit(self) + self.anilist_entry.setPlaceholderText( + "Use this if you know what anime it is and you just need the scene details" + ) + layout.addWidget(self.anilist_entry) + + search_button = PrimaryPushButton() + search_button.setText("Search") + search_button.clicked.connect(self.onClickSearch) + layout.addWidget(search_button) + + def open_image(self): + # options = QFileDialog.Options() + file_path, _ = QFileDialog.getOpenFileName( + self, + "Open Image to Search", + "", + "Image Files (*.jpg *.png *.bmp);;All Files (*)", + ) + + if file_path: + self.img_path = file_path + self.file_path_label.setText(file_path) + + def returnToMenu(self): + self.stacked_widget.setCurrentWidget(self.main_menu_widget) + self.img_path = "" + self.file_path_label.setText("") # Use self.file_path_label instead of self.main_menu_widget.file_path_label + + def onClickThemeIcon(self): + if self.ctheme == "dark": + self.ctheme = "light" + qdarktheme.setup_theme("light") + else: + self.ctheme = "dark" + qdarktheme.setup_theme("dark") + self.onThemeIconVisibilityChanged() + + def onThemeIconVisibilityChanged(self): + if self.ctheme == "dark": + self.themes_button.setIcon(QIcon("icons/dark.png")) + else: + self.themes_button.setIcon(QIcon("icons/light.png")) + + def onClickSearch(self): + self.img_url = self.img_url_entry.text() + anilist_id = self.anilist_entry.text() + iad_status = self.checkbox_iad.isChecked() + rbb_status = self.checkbox_rbb.isChecked() + anilist_status = anilist_id if anilist_id else None + + if self.img_url or self.img_path != "": + while self.layout().count(): + item = self.layout().takeAt(0) + widget = item.widget() + if widget is not None: + widget.deleteLater() + + if self.checkbox_iad.isChecked(): + iad_status = True + else: + iad_status = False + + if self.checkbox_rbb.isChecked(): + rbb_status = True + else: + rbb_status = False + + if anilist_id == "": + anilist_status = None + else: + anilist_status = anilist_id + + if self.img_url == "": + search.search_img(self, anilist_info=anilist_status, rbb=rbb_status) + else: + search.search_url(self) + + if iad_status is True: + json_operations.json_to_tabular(self, include_all_details=True) + else: + json_operations.json_to_tabular(self, include_all_details=False) + + else: + dlg = QMessageBox(self) + dlg.setWindowTitle("Error") + dlg.setText("Select any Image or Enter any URL to search") + dlg.setStandardButtons(QMessageBox.StandardButton.Ok) + button = dlg.exec() + + if button == QMessageBox.StandardButton.Ok: + pass + else: + pass diff --git a/src/main.py b/src/main.py index 58ae0e4..e28793a 100644 --- a/src/main.py +++ b/src/main.py @@ -5,191 +5,77 @@ from qfluentwidgets import * from qfluentwidgets import FluentIcon as FIF from qframelesswindow import * - +import AnimeSearch import qdarktheme from PyQt6.QtCore import * from PyQt6.QtGui import * from PyQt6.QtWidgets import * -class App(QMainWindow): +class Window(MSFluentWindow): + """ Main window class. Uses MSFLuentWindow to imitate the Windows 11 FLuent Design windows. """ + def __init__(self): + # self.isMicaEnabled = False super().__init__() - - self.setWindowTitle("AnimeSnap") - self.setGeometry(100, 100, 450, 150) - - # Create a stacked widget to manage different screens - self.stacked_widget = QStackedWidget(self) - self.setCentralWidget(self.stacked_widget) - - # Create the main menu widget - self.main_menu_widget = QWidget(self) - self.stacked_widget.addWidget(self.main_menu_widget) - - self.img_path = "" - self.img_url = "" - self.anilist_id = "" - self.ctheme = "dark" - - central_widget = QWidget(self) - self.setCentralWidget(central_widget) - - layout = QVBoxLayout() - central_widget.setLayout(layout) - - self.buttons_frame = QWidget(self) - layout.addWidget(self.buttons_frame) - - # Create a horizontal layout - top_layout = QHBoxLayout() - button_layout = QHBoxLayout() - checkbox_layout = QHBoxLayout() - - theme_icon = QIcon("icons/dark.png") - self.themes_button = QPushButton(self) - self.themes_button.setIconSize(QSize(23, 23)) - self.themes_button.clicked.connect(self.onClickThemeIcon) - self.themes_button.setIcon(theme_icon) - self.themes_button.setText("") - self.themes_button.setFixedSize(23, 23) - top_layout.addStretch() - top_layout.addWidget(self.themes_button) - - layout.addLayout(top_layout) - - layout.addWidget(QLabel("")) - - self.img_url_entry = QLineEdit(self) - self.img_url_entry.setPlaceholderText("Enter image URL or Upload a image") - - self.file_path_label = QLabel("") - - button_layout.addWidget(self.img_url_entry) - - open_image_icon = QIcon("icons/folder.png") - self.open_image_button = QPushButton(self) - self.open_image_button.clicked.connect(self.open_image) - self.open_image_button.setIcon(open_image_icon) - self.open_image_button.setIconSize(QSize(23, 23)) - self.open_image_button.setFixedSize(28, 28) - button_layout.addWidget(self.open_image_button) - - layout.addLayout(button_layout) # Add the button layout to the main layout - layout.addWidget(self.file_path_label) - - layout.addWidget(QLabel("")) - - layout.addLayout(checkbox_layout) # Add the checkbox layout to the main layout - - self.checkbox_rbb = QCheckBox("Remove Black Borders") - checkbox_layout.addWidget(self.checkbox_rbb) - - self.checkbox_iad = QCheckBox("Include All Details") - checkbox_layout.addWidget(self.checkbox_iad) - - layout.addWidget(QLabel("")) - - layout.addWidget(QLabel("Anilist Anime ID [OPTIONAL] [https://anilist.co/]")) - - self.anilist_entry = QLineEdit(self) - self.anilist_entry.setPlaceholderText( - "Use this if you know what anime it is and you just need the scene details" - ) - layout.addWidget(self.anilist_entry) - - search_button = QPushButton("Search") - search_button.clicked.connect(self.onClickSearch) - layout.addWidget(search_button) - - def open_image(self): - # options = QFileDialog.Options() - file_path, _ = QFileDialog.getOpenFileName( - self, - "Open Image to Search", - "", - "Image Files (*.jpg *.png *.bmp);;All Files (*)", + #self.setTitleBar(CustomTitleBar(self)) + #self.tabBar = self.titleBar.tabBar # type: TabBar + + setTheme(Theme.DARK) + + + # create sub interface + self.homeInterface = AnimeSearch.App() + # self.settingInterface = Settings() + # self.settingInterface.setObjectName("markdownInterface") + + + self.initNavigation() + self.initWindow() + + def initNavigation(self): + self.addSubInterface(self.homeInterface, FIF.EDIT, 'Write', FIF.EDIT, NavigationItemPosition.TOP) + # self.addSubInterface(self.settingInterface, FIF.SETTING, 'Settings', FIF.SETTING, NavigationItemPosition.BOTTOM) + self.navigationInterface.addItem( + routeKey='Help', + icon=FIF.INFO, + text='About', + onClick=self.showMessageBox, + selectable=False, + position=NavigationItemPosition.BOTTOM) + + self.navigationInterface.setCurrentItem( + self.homeInterface.objectName()) + + def initWindow(self): + self.resize(1100, 750) + self.setWindowIcon(QIcon('resource/icon.ico')) + self.setWindowTitle('ZenNotes') + + w, h = 1200, 800 + self.move(w // 2 - self.width() // 2, h // 2 - self.height() // 2) + + def showMessageBox(self): + w = MessageBox( + 'ZenNotes 📝', + ( + "Version : 1.1" + + "\n" + "\n" + "\n" + "💝 I hope you'll enjoy using ZenNotes as much as I did while coding it 💝" + "\n" + "\n" + "\n" + + "Made with 💖 By Rohan Kishore" + ), + self ) + w.yesButton.setText('GitHub') + w.cancelButton.setText('Return') + + if w.exec(): + QDesktopServices.openUrl(QUrl("https://github.com/rohankishore/")) - if file_path: - self.img_path = file_path - self.file_path_label.setText(file_path) - - def returnToMenu(self): - self.stacked_widget.setCurrentWidget(self.main_menu_widget) - self.img_path = "" - self.file_path_label.setText("") # Use self.file_path_label instead of self.main_menu_widget.file_path_label - - def onClickThemeIcon(self): - if self.ctheme == "dark": - self.ctheme = "light" - qdarktheme.setup_theme("light") - else: - self.ctheme = "dark" - qdarktheme.setup_theme("dark") - self.onThemeIconVisibilityChanged() - - def onThemeIconVisibilityChanged(self): - if self.ctheme == "dark": - self.themes_button.setIcon(QIcon("icons/dark.png")) - else: - self.themes_button.setIcon(QIcon("icons/light.png")) - - def onClickSearch(self): - self.img_url = self.img_url_entry.text() - anilist_id = self.anilist_entry.text() - iad_status = self.checkbox_iad.isChecked() - rbb_status = self.checkbox_rbb.isChecked() - anilist_status = anilist_id if anilist_id else None - - if self.img_url or self.img_path != "": - while self.layout().count(): - item = self.layout().takeAt(0) - widget = item.widget() - if widget is not None: - widget.deleteLater() - - if self.checkbox_iad.isChecked(): - iad_status = True - else: - iad_status = False - - if self.checkbox_rbb.isChecked(): - rbb_status = True - else: - rbb_status = False - - if anilist_id == "": - anilist_status = None - else: - anilist_status = anilist_id - - if self.img_url == "": - search.search_img(self, anilist_info=anilist_status, rbb=rbb_status) - else: - search.search_url(self) - - if iad_status is True: - json_operations.json_to_tabular(self, include_all_details=True) - else: - json_operations.json_to_tabular(self, include_all_details=False) - - else: - dlg = QMessageBox(self) - dlg.setWindowTitle("Error") - dlg.setText("Select any Image or Enter any URL to search") - dlg.setStandardButtons(QMessageBox.StandardButton.Ok) - button = dlg.exec() - - if button == QMessageBox.StandardButton.Ok: - pass - else: - pass if __name__ == "__main__": app = QApplication(sys.argv) qdarktheme.setup_theme("dark") - window = App() + window = Window() window.show() sys.exit(app.exec()) From 40a8f9bcd26a5ec53e41967d656848ecff08a40b Mon Sep 17 00:00:00 2001 From: Rohan Kishore Date: Sun, 18 Aug 2024 00:41:40 +0530 Subject: [PATCH 06/14] fluent design init --- src/AnimeSearch.py | 12 +++++++----- src/main.py | 6 +++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/AnimeSearch.py b/src/AnimeSearch.py index 1a7c917..76493d4 100644 --- a/src/AnimeSearch.py +++ b/src/AnimeSearch.py @@ -57,10 +57,10 @@ def __init__(self): layout.addWidget(QLabel("")) - self.img_url_entry = QLineEdit(self) + self.img_url_entry = LineEdit(self) self.img_url_entry.setPlaceholderText("Enter image URL or Upload an image") - self.file_path_label = QLabel("") + self.file_path_label = CaptionLabel() button_layout.addWidget(self.img_url_entry) @@ -79,17 +79,19 @@ def __init__(self): layout.addLayout(checkbox_layout) # Add the checkbox layout to the main layout - self.checkbox_rbb = QCheckBox("Remove Black Borders") + self.checkbox_rbb = CheckBox() + self.checkbox_rbb.setText("Remove Black Borders") checkbox_layout.addWidget(self.checkbox_rbb) - self.checkbox_iad = QCheckBox("Include All Details") + self.checkbox_iad = CheckBox() + self.checkbox_iad.setText("Include All Details") checkbox_layout.addWidget(self.checkbox_iad) layout.addWidget(QLabel("")) layout.addWidget(QLabel("Anilist Anime ID [OPTIONAL] [https://anilist.co/]")) - self.anilist_entry = QLineEdit(self) + self.anilist_entry = LineEdit(self) self.anilist_entry.setPlaceholderText( "Use this if you know what anime it is and you just need the scene details" ) diff --git a/src/main.py b/src/main.py index e28793a..d86b86e 100644 --- a/src/main.py +++ b/src/main.py @@ -34,7 +34,7 @@ def __init__(self): self.initWindow() def initNavigation(self): - self.addSubInterface(self.homeInterface, FIF.EDIT, 'Write', FIF.EDIT, NavigationItemPosition.TOP) + self.addSubInterface(self.homeInterface, FIF.SEARCH, "Find Anime", FIF.SEARCH, NavigationItemPosition.TOP) # self.addSubInterface(self.settingInterface, FIF.SETTING, 'Settings', FIF.SETTING, NavigationItemPosition.BOTTOM) self.navigationInterface.addItem( routeKey='Help', @@ -48,7 +48,7 @@ def initNavigation(self): self.homeInterface.objectName()) def initWindow(self): - self.resize(1100, 750) + self.resize(500, 160) self.setWindowIcon(QIcon('resource/icon.ico')) self.setWindowTitle('ZenNotes') @@ -75,7 +75,7 @@ def showMessageBox(self): if __name__ == "__main__": app = QApplication(sys.argv) - qdarktheme.setup_theme("dark") + #qdarktheme.setup_theme("dark") window = Window() window.show() sys.exit(app.exec()) From f308ff89cde49ae96749274958d21661d915514e Mon Sep 17 00:00:00 2001 From: Rohan Kishore Date: Sun, 18 Aug 2024 00:43:25 +0530 Subject: [PATCH 07/14] fluent design init --- src/AnimeSearch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AnimeSearch.py b/src/AnimeSearch.py index 76493d4..4b07e96 100644 --- a/src/AnimeSearch.py +++ b/src/AnimeSearch.py @@ -64,7 +64,7 @@ def __init__(self): button_layout.addWidget(self.img_url_entry) - open_image_icon = QIcon("icons/folder.png") + open_image_icon = FIF.FOLDER self.open_image_button = QPushButton(self) self.open_image_button.clicked.connect(self.open_image) self.open_image_button.setIcon(open_image_icon) From 08ec11f424e4a2024c34910484f584892a6c1f40 Mon Sep 17 00:00:00 2001 From: Rohan Kishore Date: Sun, 18 Aug 2024 00:48:43 +0530 Subject: [PATCH 08/14] fluent design init --- src/AnimeSearch.py | 4 ++-- src/main.py | 18 +++++++----------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/AnimeSearch.py b/src/AnimeSearch.py index 4b07e96..304590f 100644 --- a/src/AnimeSearch.py +++ b/src/AnimeSearch.py @@ -64,8 +64,8 @@ def __init__(self): button_layout.addWidget(self.img_url_entry) - open_image_icon = FIF.FOLDER - self.open_image_button = QPushButton(self) + open_image_icon = QIcon("icons/folder.png") + self.open_image_button = PushButton(self) self.open_image_button.clicked.connect(self.open_image) self.open_image_button.setIcon(open_image_icon) self.open_image_button.setIconSize(QSize(23, 23)) diff --git a/src/main.py b/src/main.py index d86b86e..a15cbe7 100644 --- a/src/main.py +++ b/src/main.py @@ -1,15 +1,11 @@ -import sys -import os -import json_operations -import search +from PyQt6.QtCore import * +from PyQt6.QtGui import * +from PyQt6.QtWidgets import * from qfluentwidgets import * from qfluentwidgets import FluentIcon as FIF from qframelesswindow import * + import AnimeSearch -import qdarktheme -from PyQt6.QtCore import * -from PyQt6.QtGui import * -from PyQt6.QtWidgets import * class Window(MSFluentWindow): @@ -57,10 +53,10 @@ def initWindow(self): def showMessageBox(self): w = MessageBox( - 'ZenNotes 📝', + 'AnimeSnap đŸ¯', ( - "Version : 1.1" - + "\n" + "\n" + "\n" + "💝 I hope you'll enjoy using ZenNotes as much as I did while coding it 💝" + "\n" + "\n" + "\n" + + "Version : 3.0" + + "\n" + "\n" + "\n" + "💝 I hope you'll enjoy using AnimeSnap as much as I did while coding it 💝" + "\n" + "\n" + "\n" + "Made with 💖 By Rohan Kishore" ), self From b6ec785d8ed151cf75086b5f12466c40e1991f07 Mon Sep 17 00:00:00 2001 From: Rohan Kishore Date: Sun, 18 Aug 2024 00:48:50 +0530 Subject: [PATCH 09/14] fluent design init --- src/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.py b/src/main.py index a15cbe7..38538dd 100644 --- a/src/main.py +++ b/src/main.py @@ -65,7 +65,7 @@ def showMessageBox(self): w.cancelButton.setText('Return') if w.exec(): - QDesktopServices.openUrl(QUrl("https://github.com/rohankishore/")) + QDesktopServices.openUrl(QUrl("https://github.com/rohankishore/AnimeSnap")) From b12be8b8f618778e7a11f0b1f2fe5e0a01da0719 Mon Sep 17 00:00:00 2001 From: Rohan Kishore Date: Sun, 18 Aug 2024 00:57:58 +0530 Subject: [PATCH 10/14] button borderless --- src/AnimeSearch.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/AnimeSearch.py b/src/AnimeSearch.py index 304590f..72e519e 100644 --- a/src/AnimeSearch.py +++ b/src/AnimeSearch.py @@ -45,6 +45,11 @@ def __init__(self): theme_icon = QIcon("icons/dark.png") self.themes_button = QPushButton(self) + self.themes_button.setStyleSheet(""" + QPushButton { + border: none; + } + """) self.themes_button.setIconSize(QSize(23, 23)) self.themes_button.clicked.connect(self.onClickThemeIcon) self.themes_button.setIcon(theme_icon) @@ -65,7 +70,12 @@ def __init__(self): button_layout.addWidget(self.img_url_entry) open_image_icon = QIcon("icons/folder.png") - self.open_image_button = PushButton(self) + self.open_image_button = QPushButton(self) + self.open_image_button.setStyleSheet(""" + QPushButton { + border: none; + } + """) self.open_image_button.clicked.connect(self.open_image) self.open_image_button.setIcon(open_image_icon) self.open_image_button.setIconSize(QSize(23, 23)) From 7ea082c07250a85fb89ce10b30564ca0996596d6 Mon Sep 17 00:00:00 2001 From: Rohan Kishore Date: Sun, 18 Aug 2024 01:01:32 +0530 Subject: [PATCH 11/14] button borderless --- src/AnimeSearch.py | 36 ++++-------------------------------- src/main.py | 2 +- 2 files changed, 5 insertions(+), 33 deletions(-) diff --git a/src/AnimeSearch.py b/src/AnimeSearch.py index 72e519e..9073e1b 100644 --- a/src/AnimeSearch.py +++ b/src/AnimeSearch.py @@ -13,12 +13,14 @@ class App(QWidget): - def __init__(self): - super().__init__() + def __init__(self, parent=None): + super().__init__(parent) self.setObjectName("AnimeSnap") self.setGeometry(100, 100, 450, 150) + self.mainApp = parent + # Create a stacked widget to manage different screens self.stacked_widget = QStackedWidget(self) @@ -43,21 +45,6 @@ def __init__(self): button_layout = QHBoxLayout() checkbox_layout = QHBoxLayout() - theme_icon = QIcon("icons/dark.png") - self.themes_button = QPushButton(self) - self.themes_button.setStyleSheet(""" - QPushButton { - border: none; - } - """) - self.themes_button.setIconSize(QSize(23, 23)) - self.themes_button.clicked.connect(self.onClickThemeIcon) - self.themes_button.setIcon(theme_icon) - self.themes_button.setText("") - self.themes_button.setFixedSize(23, 23) - top_layout.addStretch() - top_layout.addWidget(self.themes_button) - layout.addLayout(top_layout) layout.addWidget(QLabel("")) @@ -130,21 +117,6 @@ def returnToMenu(self): self.img_path = "" self.file_path_label.setText("") # Use self.file_path_label instead of self.main_menu_widget.file_path_label - def onClickThemeIcon(self): - if self.ctheme == "dark": - self.ctheme = "light" - qdarktheme.setup_theme("light") - else: - self.ctheme = "dark" - qdarktheme.setup_theme("dark") - self.onThemeIconVisibilityChanged() - - def onThemeIconVisibilityChanged(self): - if self.ctheme == "dark": - self.themes_button.setIcon(QIcon("icons/dark.png")) - else: - self.themes_button.setIcon(QIcon("icons/light.png")) - def onClickSearch(self): self.img_url = self.img_url_entry.text() anilist_id = self.anilist_entry.text() diff --git a/src/main.py b/src/main.py index 38538dd..29e410a 100644 --- a/src/main.py +++ b/src/main.py @@ -21,7 +21,7 @@ def __init__(self): # create sub interface - self.homeInterface = AnimeSearch.App() + self.homeInterface = AnimeSearch.App(self) # self.settingInterface = Settings() # self.settingInterface.setObjectName("markdownInterface") From 91c872125cf6ae538c1e98a63461d89f496e2779 Mon Sep 17 00:00:00 2001 From: Rohan Kishore <109947257+rohankishore@users.noreply.github.com> Date: Sun, 18 Aug 2024 01:08:19 +0530 Subject: [PATCH 12/14] add icon --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index bd926e8..e1538fb 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ +
+ +![icon](https://github.com/user-attachments/assets/e7244321-0452-4a9d-b24d-1b70eedb16e7) + +
+

⛩ī¸ AnimeSnap đŸĨ

From 81fae8edc6f805477b144a6c1eb0b3e73f1b06e7 Mon Sep 17 00:00:00 2001 From: Rohan Kishore Date: Sun, 18 Aug 2024 01:18:20 +0530 Subject: [PATCH 13/14] fluent design + icon --- src/AnimeSearch.py | 4 +++- src/icons/icon.png | Bin 0 -> 1782 bytes src/main.py | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 src/icons/icon.png diff --git a/src/AnimeSearch.py b/src/AnimeSearch.py index 9073e1b..998ecfd 100644 --- a/src/AnimeSearch.py +++ b/src/AnimeSearch.py @@ -86,7 +86,9 @@ def __init__(self, parent=None): layout.addWidget(QLabel("")) - layout.addWidget(QLabel("Anilist Anime ID [OPTIONAL] [https://anilist.co/]")) + anilist_label = CaptionLabel() + anilist_label.setText("Anilist Anime ID [OPTIONAL] [https://anilist.co/]") + layout.addWidget(anilist_label) self.anilist_entry = LineEdit(self) self.anilist_entry.setPlaceholderText( diff --git a/src/icons/icon.png b/src/icons/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a013eb880454505fff5adae44b16ac84326b462d GIT binary patch literal 1782 zcmVJ)kjF)&@`DAfVstFD-@M9Cxh9m!i>$j$TH`(?Yz_@3G$YZa&{8Te~YOO~-MXXnz{%#0Yr?rdg#b8j>pTSae`7|X2kxGS4 z*Ktbw`}@cGtvZ`sKTPCw@8F%)h&r-M*f|s z59_c+=7E%<>BW(pH&uyPcwD5@VgHr#D+byT zqM+4pKi%ISxlUq)r4XS2#X)P^l<|F0w}h;X3`gWIdU^H1gCf~r1T49X*@EIc2ZD=f{FhkDcLGTHP}g5U*wA=Ie9>e11E_%I|R zG}8^>zfGM`*IdY$0V~ulTiV{<-e+qcDIwTaH?}=4X^Z=zoH?B_{0)E}d?sY*k_Cyr z&@ho0;q=7?$aSYSDuh0Dwf%@}h=c>18GI}Oi*%j(LSv$zln{2=Hkqdf2ge_4wL{+NY;*8Bng~8CD>wnE+UlA!#l6SqOw0E_tWwr! z@lX~1l&KSL(ItW4j-$;)A0smiTK?O0X>s8OGsv|a0L&|fCN0&R*P#W5@VPpE0dwQj z2<=Vw76&lnfpR`#7*dTrHa&<$ZD=TPRG1~=_cg% zo4gMw7F9mb>3Nh8MvIOKFyXSq`a3FRvvP<|Ct9XhlyY-ZUaH4T&8C#c$10DymCEJ% z3x!$qS9Ff%ZVCI&7Ze4&g+_x9U%rmtbfLg!7JO*2v4PJGW7!I~^NnN0`a02P-itr+ z4-;R$RCONnpto8|2G3u;QgvRxRx-Jq(z&)a)(uO*{dOCBNJS@`RXTvvQ)PK!97Pgl z6%DBzJZsh(kwe2EfremyxT5pr^4Khc4xs~(dBa~mxAq-Yo}r^4 z)NCr!f$kkX)U4OXM4>YnYz#i?qkTNX06^#1)nLvIorY~`Y2Q4fxOmh ziUaJNLVf_hIyvDpeQ)f`@H^ah-LVYvxtw|q*-S>|kswp8j`O$%zK(0FC1t&?uH~|- ztLsL&R8lgy!k3Yt2W=t`nQ^~c6c_M}nSxGIDcs@d2_!+@{=7i5K&syt?P$a0B>h zY#yRF`cR^qfK*df>lVp2n+!qect?dnYsm6sh(#Dt)P;G0;MF8NUX zlfY)TEEfAz_4+XL82nFZ>a`9Y=U3!c5jB^~bwQ^My92EusBg5QSMk zrg=1o^fc>~E=MP@o{{PfGERCNyZyDV Date: Sun, 18 Aug 2024 01:22:42 +0530 Subject: [PATCH 14/14] updated screenshots --- README.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/README.md b/README.md index e1538fb..8fd2444 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ And much more if you check `Include All Details`. It will also show multiple res #### Using the App -![image](https://github.com/rohankishore/AnimeSnap/assets/109947257/17b36284-4231-4747-b047-185e892b9252) +![image](https://github.com/user-attachments/assets/fc462b43-856f-410c-b998-f6841e2fd7df) You can either use an image link or upload an image from your PC. With v2.0, there are 2 new checkboxes. Removing black bars will help to increase the accuracy of the overall results if there are any black borders in your image, though the processing time may slightly increase. By checking `Include All Details`, you can get all the info that you get by uploading to JSON. @@ -41,12 +41,6 @@ Also, now you can filter results by using [Anilist](https://anilist.co/) ID. Thi
-## 🌊 Demo - -![image](https://github.com/rohankishore/AnimeSnap/assets/109947257/016033db-b51e-4521-afef-5d878fdf8b16) - -
- ## 💖 Credits This project was made possible just because of [soruly](https://github.com/soruly)'s [trace.moe API](https://github.com/soruly/trace.moe-api).