Today, I worked with art artificial intelligence, to create tool for my game development.
I used python and PyQt6 and this tool help me to remove border, resize, split, rename and save images as PNG file type for Godot game engine.



Is a blog about python programming language. You can see my work with python programming language, tutorials and news.
python catafest_build_package_001.py
🔍 Verificare module standard...
[✓] Modul standard 'json' este disponibil.
[✓] Modul standard 'subprocess' este disponibil.
[✓] Modul standard 'platform' este disponibil.
[✓] Modul standard 'datetime' este disponibil.
[✓] Modul standard 'os' este disponibil.
[✓] Modul standard 'sys' este disponibil.
📦 Verificare și instalare module pip...
[✓] Modulul 'PyQt6' este deja instalat.
[✓] Modulul 'build' este deja instalat.
* Creating isolated environment: venv+pip...
* Installing packages in isolated environment:
- setuptools
- wheel
...
import os
import subprocess
from PyQt6.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QPushButton,
QListWidget, QMessageBox
)
# fisier download : yt-dlp.exe -vU https://www.youtube.com/watch?v=xxxxxx -f bestvideo*+bestaudio/best
FOLDER_PATH = r"D:\Software"
class FFmpegMerger(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Combinare Video + Audio cu FFmpeg")
self.resize(600, 400)
self.layout = QVBoxLayout()
self.file_list = QListWidget()
self.process_button = QPushButton("Prelucrează în MP4")
self.layout.addWidget(self.file_list)
self.layout.addWidget(self.process_button)
self.setLayout(self.layout)
self.process_button.clicked.connect(self.process_files)
self.populate_file_list()
def populate_file_list(self):
files = os.listdir(FOLDER_PATH)
video_files = [f for f in files if f.endswith(".f401.mp4")]
audio_files = [f for f in files if f.endswith(".f251-9.webm")]
base_names = set(f.split(".f401.mp4")[0] for f in video_files)
candidates = []
for base in base_names:
audio_name = f"{base}.f251-9.webm"
output_name = f"{base}.mp4"
if audio_name in audio_files and output_name not in files:
candidates.append(base)
for name in candidates:
self.file_list.addItem(name)
def process_files(self):
for i in range(self.file_list.count()):
base = self.file_list.item(i).text()
video_path = os.path.join(FOLDER_PATH, f"{base}.f401.mp4")
audio_path = os.path.join(FOLDER_PATH, f"{base}.f251-9.webm")
output_path = os.path.join(FOLDER_PATH, f"{base}.mp4")
cmd = [
"ffmpeg",
"-i", video_path,
"-i", audio_path,
"-c:v", "copy",
"-c:a", "aac",
"-strict", "experimental",
output_path
]
try:
subprocess.run(cmd, check=True)
except subprocess.CalledProcessError as e:
QMessageBox.critical(self, "Eroare", f"Eroare la procesarea {base}: {e}")
return
QMessageBox.information(self, "Succes", "Toate fișierele au fost prelucrate cu succes!")
if __name__ == "__main__":
app = QApplication([])
window = FFmpegMerger()
window.show()
app.exec()
# Generate star polygon vertices
points_cw = []
points_ccw = []
for i in range(steps):
t = 2 * math.pi * i / steps
r = outer_radius if i % 2 == 0 else inner_radius
x_cw = center[0] + r * math.cos(t)
y_cw = center[1] + r * math.sin(t)
x_ccw = center[0] + r * math.cos(-t + math.pi / max(lobes, 1))
y_ccw = center[1] + r * math.sin(-t + math.pi / max(lobes, 1))
points_cw.append((x_cw, y_cw))
points_ccw.append((x_ccw, y_ccw))
import os
import unittest
from PIL import Image, ImageDraw, ImageFont, ImageQt
import shutil
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QFileDialog, QLabel, QVBoxLayout, QWidget, QComboBox
from PyQt6.QtGui import QPixmap
from PyQt6.QtCore import Qt
import sys
def create_test_image(path, size, number):
img = Image.new('RGBA', size, (255, 255, 255, 255))
draw = ImageDraw.Draw(img)
# Simplified to just draw the number with a basic color background
draw.rectangle((0, 0, size[0], size[1]), fill=(0, 100 * number % 255, 0, 255))
try:
font = ImageFont.load_default()
except:
font = None
draw.text((size[0]//2-5, size[1]//2-5), str(number), fill=(255, 255, 255, 255), font=font)
img.save(path, 'PNG')
def merge_sprites(folder_path, output_horizontal, output_vertical):
images = [Image.open(os.path.join(folder_path, f)) for f in os.listdir(folder_path) if f.endswith(('.png', '.jpg', '.jpeg'))]
if not images:
return None, None
width, height = images[0].size
# Horizontal merge
total_width = width * len(images)
horizontal_image = Image.new('RGBA', (total_width, height))
for i, img in enumerate(images):
horizontal_image.paste(img, (i * width, 0))
horizontal_image.save(output_horizontal, 'PNG')
# Vertical merge
total_height = height * len(images)
vertical_image = Image.new('RGBA', (width, total_height))
for i, img in enumerate(images):
vertical_image.paste(img, (0, i * height))
vertical_image.save(output_vertical, 'PNG')
return horizontal_image, vertical_image
class TestSpriteMerger(unittest.TestCase):
def setUp(self):
self.test_folder = 'test_images'
self.size = (50, 20)
os.makedirs(self.test_folder, exist_ok=True)
for i in range(3):
create_test_image(os.path.join(self.test_folder, f'test_{i+1}.png'), self.size, i+1)
def test_merge_horizontal(self):
output_h = 'test_merged_horizontal.png'
output_v = 'test_merged_vertical.png'
h_img, _ = merge_sprites(self.test_folder, output_h, output_v)
self.assertIsNotNone(h_img, "Horizontal merge failed")
self.assertEqual(h_img.size, (self.size[0] * 3, self.size[1]))
def test_merge_vertical(self):
output_h = 'test_merged_horizontal.png'
output_v = 'test_merged_vertical.png'
_, v_img = merge_sprites(self.test_folder, output_h, output_v)
self.assertIsNotNone(v_img, "Vertical merge failed")
self.assertEqual(v_img.size, (self.size[0], self.size[1] * 3))
def tearDown(self):
if os.path.exists(self.test_folder):
shutil.rmtree(self.test_folder)
for f in ['test_merged_horizontal.png', 'test_merged_vertical.png']:
if os.path.exists(f):
os.remove(f)
class SpriteMergerApp(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Sprite Merger")
self.setGeometry(100, 100, 800, 600)
self.folder_path = ""
layout = QVBoxLayout()
self.select_button = QPushButton("Select Folder")
self.select_button.clicked.connect(self.select_folder)
layout.addWidget(self.select_button)
self.merge_type = QComboBox()
self.merge_type.addItems(["Horizontal", "Vertical"])
layout.addWidget(self.merge_type)
self.process_button = QPushButton("Process Selected Folder")
self.process_button.clicked.connect(self.process_folder)
layout.addWidget(self.process_button)
self.test_button = QPushButton("Run Unit Test")
self.test_button.clicked.connect(self.run_unit_test)
layout.addWidget(self.test_button)
self.result_label = QLabel("No image processed")
layout.addWidget(self.result_label)
self.image_label = QLabel()
layout.addWidget(self.image_label)
container = QWidget()
container.setLayout(layout)
self.setCentralWidget(container)
def select_folder(self):
self.folder_path = QFileDialog.getExistingDirectory(self, "Select Sprite Folder")
self.result_label.setText(f"Selected: {self.folder_path}")
def process_folder(self):
if not self.folder_path:
self.result_label.setText("Please select a folder first")
return
h_img, v_img = merge_sprites(self.folder_path, 'merged_horizontal.png', 'merged_vertical.png')
selected_type = self.merge_type.currentText()
img = h_img if selected_type == "Horizontal" else v_img
if img:
pixmap = QPixmap.fromImage(ImageQt.ImageQt(img))
self.image_label.setPixmap(pixmap.scaled(700, 500, aspectRatioMode=Qt.AspectRatioMode.KeepAspectRatio))
self.result_label.setText(f"{selected_type} merge completed")
else:
self.result_label.setText(f"{selected_type} merge failed")
def run_unit_test(self):
suite = unittest.TestLoader().loadTestsFromTestCase(TestSpriteMerger)
result = unittest.TextTestRunner().run(suite)
test_folder = 'test_images'
os.makedirs(test_folder, exist_ok=True)
for i in range(3):
create_test_image(os.path.join(test_folder, f'test_{i+1}.png'), (50, 20), i+1)
h_img, v_img = merge_sprites(test_folder, 'test_merged_horizontal.png', 'test_merged_vertical.png')
selected_type = self.merge_type.currentText()
img = h_img if selected_type == "Horizontal" else v_img
if img:
pixmap = QPixmap.fromImage(ImageQt.ImageQt(img))
self.image_label.setPixmap(pixmap.scaled(700, 500, aspectRatioMode=Qt.AspectRatioMode.KeepAspectRatio))
self.result_label.setText(f"Unit tests: {result.testsRun} run, {len(result.failures)} failed, showing {selected_type.lower()} merge")
else:
self.result_label.setText(f"Unit tests: {result.testsRun} run, {len(result.failures)} failed, merge failed")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = SpriteMergerApp()
window.show()
sys.exit(app.exec())
import sys
import os
from datetime import datetime
from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, QFileDialog, QLineEdit, QCheckBox, QLabel, QMessageBox
from PyQt6.QtCore import Qt
from PIL import Image
class ResizeApp(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Image Resizer")
self.setGeometry(100, 100, 400, 200)
layout = QVBoxLayout()
central_widget = QWidget()
central_widget.setLayout(layout)
self.setCentralWidget(central_widget)
self.folder_button = QPushButton("Select Folder")
self.folder_button.clicked.connect(self.select_folder)
layout.addWidget(self.folder_button)
self.width_edit = QLineEdit("800")
self.width_edit.setPlaceholderText("Width (px)")
layout.addWidget(QLabel("Width:"))
layout.addWidget(self.width_edit)
self.height_edit = QLineEdit("600")
self.height_edit.setPlaceholderText("Height (px)")
layout.addWidget(QLabel("Height:"))
layout.addWidget(self.height_edit)
self.aspect_ratio = QCheckBox("Maintain Aspect Ratio")
self.aspect_ratio.setChecked(True)
layout.addWidget(self.aspect_ratio)
self.resize_button = QPushButton("Resize Images")
self.resize_button.clicked.connect(self.resize_images)
layout.addWidget(self.resize_button)
self.folder_path = ""
def select_folder(self):
self.folder_path = QFileDialog.getExistingDirectory(self, "Select Image Folder")
if self.folder_path:
self.folder_button.setText(f"Selected: {os.path.basename(self.folder_path)}")
def resize_images(self):
if not self.folder_path:
QMessageBox.warning(self, "Error", "Please select a folder.")
return
try:
width = int(self.width_edit.text())
height = int(self.height_edit.text())
except ValueError:
QMessageBox.warning(self, "Error", "Please enter valid width and height.")
return
if width <= 0 or height <= 0:
QMessageBox.warning(self, "Error", "Width and height must be positive.")
return
date_str = datetime.now().strftime("%d%m%y_%H%M")
aspect_str = "asp_on" if self.aspect_ratio.isChecked() else "asp_off"
output_folder = os.path.join(self.folder_path, f"resized_{date_str}_{height}_{aspect_str}")
os.makedirs(output_folder, exist_ok=True)
for file_name in os.listdir(self.folder_path):
if file_name.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif')):
image_path = os.path.join(self.folder_path, file_name)
try:
with Image.open(image_path) as img:
if self.aspect_ratio.isChecked():
img.thumbnail((width, height), Image.Resampling.LANCZOS)
else:
img = img.resize((width, height), Image.Resampling.LANCZOS)
output_path = os.path.join(output_folder, f"resized_{date_str}_{height}_{aspect_str}_{file_name}")
img.save(output_path)
except Exception as e:
QMessageBox.warning(self, "Error", f"Failed to process {file_name}: {str(e)}")
QMessageBox.information(self, "Success", f"Images resized and saved to {output_folder}!")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = ResizeApp()
window.show()
sys.exit(app.exec())
import sys
import os
import re
import shutil
import zipfile
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QPushButton, QListWidget, QFileDialog, QMessageBox, QDialog, QLabel)
from PyQt6.QtCore import Qt
class CriteriaDialog(QDialog):
def __init__(self, folder, parent=None):
super().__init__(parent)
self.setWindowTitle(f"Processing Folder: {folder}")
self.layout = QVBoxLayout(self)
self.layout.addWidget(QLabel(f"Selected folder: {folder}"))
self.ok_button = QPushButton("OK")
self.ok_button.clicked.connect(self.accept)
self.layout.addWidget(self.ok_button)
class DuplicateFinder(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Duplicate File Finder")
self.setGeometry(100, 100, 600, 400)
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
self.layout = QVBoxLayout(self.central_widget)
self.file_list = QListWidget()
self.file_list.setSelectionMode(QListWidget.SelectionMode.MultiSelection)
self.layout.addWidget(self.file_list)
button_layout = QHBoxLayout()
self.select_button = QPushButton("Select Folder")
self.select_button.clicked.connect(self.select_folder)
button_layout.addWidget(self.select_button)
self.copy_button = QPushButton("Copy To")
self.copy_button.clicked.connect(self.copy_files)
button_layout.addWidget(self.copy_button)
self.zip_button = QPushButton("Zip All")
self.zip_button.clicked.connect(self.zip_files)
button_layout.addWidget(self.zip_button)
self.delete_button = QPushButton("Delete All")
self.delete_button.clicked.connect(self.delete_files)
button_layout.addWidget(self.delete_button)
self.layout.addLayout(button_layout)
self.files = []
self.selected_folder = ""
def select_folder(self):
folder = QFileDialog.getExistingDirectory(self, "Select Folder")
if folder:
self.selected_folder = folder
dialog = CriteriaDialog(folder, self)
if dialog.exec():
self.files = []
self.file_list.clear()
self.scan_folder(folder)
self.find_duplicates()
def scan_folder(self, folder):
for root, _, files in os.walk(folder):
for file in files:
file_path = os.path.join(root, file)
self.files.append({
'path': file_path,
'name': os.path.basename(file_path),
'size': os.path.getsize(file_path),
'extension': os.path.splitext(file_path)[1]
})
def find_duplicates(self):
duplicates = self.find_by_similar_name()
self.display_duplicates(duplicates)
def find_by_similar_name(self):
duplicates = []
name_groups = {}
pattern = r'(.+?)(?:[\s_-]*\d{3,}|[\s_-]*\d{1,2}|_)?(?:\.\w+)?$'
for file in self.files:
match = re.match(pattern, file['name'])
if match:
base_name = match.group(1)
if base_name in name_groups:
name_groups[base_name].append(file)
else:
name_groups[base_name] = [file]
for base_name, files in name_groups.items():
if len(files) > 1:
duplicates.extend(files)
return duplicates
def display_duplicates(self, duplicates):
self.file_list.clear()
for file in duplicates:
self.file_list.addItem(file['path'])
def copy_files(self):
if not self.file_list.selectedItems():
QMessageBox.warning(self, "Warning", "No files selected!")
return
dest_folder = QFileDialog.getExistingDirectory(self, "Select Destination Folder")
if dest_folder:
for item in self.file_list.selectedItems():
file_path = item.text()
dest_path = os.path.join(dest_folder, os.path.basename(file_path))
shutil.copy2(file_path, dest_path)
QMessageBox.information(self, "Success", "Files copied!")
def zip_files(self):
if not self.file_list.selectedItems():
QMessageBox.warning(self, "Warning", "No files selected!")
return
zip_path = QFileDialog.getSaveFileName(self, "Save Zip File", "", "Zip Files (*.zip)")[0]
if zip_path:
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
for item in self.file_list.selectedItems():
file_path = item.text()
zipf.write(file_path, os.path.basename(file_path))
QMessageBox.information(self, "Success", "Files zipped!")
def delete_files(self):
if not self.file_list.selectedItems():
QMessageBox.warning(self, "Warning", "No files selected!")
return
reply = QMessageBox.question(self, "Confirm", "Delete selected files?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
if reply == QMessageBox.StandardButton.Yes:
for item in self.file_list.selectedItems():
os.remove(item.text())
self.file_list.clear()
QMessageBox.information(self, "Success", "Files deleted!")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = DuplicateFinder()
window.show()
sys.exit(app.exec())
import sys
from PyQt6.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout, QMenu
# diff PyQt6 versus old PyQt
from PyQt6.QtGui import QAction
from PyQt6.QtGui import QPixmap, QIcon
from PyQt6.QtCore import QTimer, Qt
class AnimatedWindow(QWidget):
def __init__(self):
super().__init__()
# set window
self.setWindowFlags(Qt.WindowType.FramelessWindowHint | Qt.WindowType.WindowStaysOnTopHint)
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
# build layout
layout = QVBoxLayout()
self.label = QLabel(self)
layout.addWidget(self.label)
self.setLayout(layout)
# load sprite sheet from Camera_256px.png file name
sprite_sheet = QPixmap("Camera_256px.png")
self.frame_width = sprite_sheet.width() // 11 # because I have 11 sprite on image
self.sprites = [sprite_sheet.copy(i * self.frame_width, 0, self.frame_width, sprite_sheet.height()) for i in range(11)]
self.current_frame = 0
#
self.timer = QTimer()
self.timer.timeout.connect(self.update_animation)
self.timer.start(150) # Schimbă frame-ul la fiecare 150 ms
#
self.resize(self.frame_width, sprite_sheet.height())
# left down on screen
screen = QApplication.primaryScreen().geometry()
self.move(10, screen.height() - self.height() - 10)
def update_animation(self):
"""Actualizează sprite-ul în QLabel"""
self.label.setPixmap(self.sprites[self.current_frame])
self.current_frame = (self.current_frame + 1) % len(self.sprites)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = AnimatedWindow()
window.show()
sys.exit(app.exec())
from PyQt6.QtWidgets import QApplication, QMainWindow, QTextEdit, QMenu
from bs4 import BeautifulSoup
class AgentPy:
"""Clasă pentru procesarea și curățarea HTML-ului."""
@staticmethod
def clean_all_styles(html_content):
soup = BeautifulSoup(html_content, 'html.parser')
for tag in soup.find_all(True):
if tag.name == "a":
attrs_to_keep = {"href": tag.attrs.get("href")} if "href" in tag.attrs else {}
tag.attrs = attrs_to_keep
else:
tag.attrs = {}
return str(soup)
@staticmethod
def clean_empty_tags(html_content):
soup = BeautifulSoup(html_content, 'html.parser')
for tag in soup.find_all(True):
if not tag.contents or all(str(content).strip() == "" for content in tag.contents):
tag.decompose()
return str(soup)
@staticmethod
def clean_duplicate_tags(html_content):
soup = BeautifulSoup(html_content, 'html.parser')
unique_tags = {}
for tag in soup.find_all(True):
tag_key = (tag.name, str(tag.attrs))
if tag_key in unique_tags:
tag.decompose()
else:
unique_tags[tag_key] = tag
return str(soup)
@staticmethod
def convert_to_html(source_code):
"""Convertim caractere speciale din cod sursă în entități HTML."""
# Creăm un dicționar pentru conversia caracterelor
html_entities = {
'<': '<',
'>': '>',
'&': '&',
'"': '"',
"'": ''',
'[': '[',
']': ']',
}
# Înlocuim caracterele în codul sursă
for char, entity in html_entities.items():
source_code = source_code.replace(char, entity)
return source_code
class HtmlEditor(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("catafest-cleaner-HTML")
self.setGeometry(100, 100, 800, 600)
# Editor de text
self.editor = QTextEdit(self)
self.setCentralWidget(self.editor)
# Meniu contextual
self.editor.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.editor.customContextMenuRequested.connect(self.show_context_menu)
def show_context_menu(self, position):
menu = QMenu(self)
clean_styles_action = menu.addAction("Clean basic HTML")
clean_styles_action.triggered.connect(self.clean_all_styles)
clean_empty_tags_action = menu.addAction("Clean Empty Tags")
clean_empty_tags_action.triggered.connect(self.clean_empty_tags)
clean_agentpy_action = menu.addAction("Clean AgentPy")
clean_agentpy_action.triggered.connect(self.clean_duplicate_tags)
convert_to_html_action = menu.addAction("Convert to HTML") # Noua opțiune
convert_to_html_action.triggered.connect(self.convert_to_html)
menu.exec(self.editor.mapToGlobal(position))
def clean_all_styles(self):
html_content = self.editor.toPlainText()
clean_html = AgentPy.clean_all_styles(html_content)
self.editor.setPlainText(clean_html)
def clean_empty_tags(self):
html_content = self.editor.toPlainText()
clean_html = AgentPy.clean_empty_tags(html_content)
self.editor.setPlainText(clean_html)
def clean_duplicate_tags(self):
html_content = self.editor.toPlainText()
clean_html = AgentPy.clean_duplicate_tags(html_content)
self.editor.setPlainText(clean_html)
def convert_to_html(self):
source_code = self.editor.toPlainText()
html_content = AgentPy.convert_to_html(source_code)
self.editor.setPlainText(html_content)
if __name__ == "__main__":
import sys
from PyQt6.QtCore import Qt
app = QApplication(sys.argv)
window = HtmlEditor()
window.show()
sys.exit(app.exec())
from PyQt6.QtWidgets import QApplication, QMainWindow, QTextEdit, QMenu from bs4 import BeautifulSoup class HtmlEditor(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("catafest-cleaner-HTML") # Titlu actualizat self.setGeometry(100, 100, 800, 600) # Editor de text self.editor = QTextEdit(self) self.setCentralWidget(self.editor) # Meniu contextual self.editor.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self.editor.customContextMenuRequested.connect(self.show_context_menu) def show_context_menu(self, position): menu = QMenu(self) clean_styles_action = menu.addAction("Clean basic HTML") clean_styles_action.triggered.connect(self.clean_all_styles) clean_empty_tags_action = menu.addAction("Clean Empty Tags") clean_empty_tags_action.triggered.connect(self.clean_empty_tags) menu.exec(self.editor.mapToGlobal(position)) def clean_all_styles(self): # Obține conținutul HTML din editor html_content = self.editor.toPlainText() # Utilizează BeautifulSoup pentru a procesa HTML-ul soup = BeautifulSoup(html_content, 'html.parser') # Elimină toate atributele, cu excepția celor din ancorele <a> for tag in soup.find_all(True): if tag.name == "a": # Păstrează doar atributul 'href' pentru <a> attrs_to_keep = {"href": tag.attrs.get("href")} if "href" in tag.attrs else {} tag.attrs = attrs_to_keep else: tag.attrs = {} # Elimină toate atributele pentru celelalte tag-uri # Actualizează conținutul editorului clean_html = str(soup) self.editor.setPlainText(clean_html) def clean_empty_tags(self): # Obține conținutul HTML din editor html_content = self.editor.toPlainText() # Utilizează BeautifulSoup pentru a procesa HTML-ul soup = BeautifulSoup(html_content, 'html.parser') # Elimină tag-urile goale for tag in soup.find_all(True): # Verifică tag-uri goale if not tag.contents or all(str(content).strip() == "" for content in tag.contents): tag.decompose() # Elimină tag-ul complet # Actualizează conținutul editorului clean_html = str(soup) self.editor.setPlainText(clean_html) if __name__ == "__main__": import sys from PyQt6.QtCore import Qt app = QApplication(sys.argv) window = HtmlEditor() window.show() sys.exit(app.exec())
import sys
import subprocess
from PyQt6.QtWidgets import (
QApplication, QMainWindow, QVBoxLayout, QTreeWidget, QTreeWidgetItem, QWidget
)
from PyQt6.QtWidgets import QHeaderView
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import QStyle
class DependencyViewer(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Dependency Checker")
# Maximizarea ferestrei la lansare
self.showMaximized()
# Creează un QTreeWidget pentru afișarea dependențelor
self.tree_widget = QTreeWidget()
self.tree_widget.setHeaderLabels(["Dependency", "Status"])
# Ajustează aliniamentul central pentru fiecare coloană
for i in range(2): # Pentru cele două coloane
self.tree_widget.headerItem().setTextAlignment(i, Qt.AlignmentFlag.AlignCenter)
# Configurarea automată a lățimii coloanelor
self.tree_widget.header().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents)
# Layout
layout = QVBoxLayout()
layout.addWidget(self.tree_widget)
container = QWidget()
container.setLayout(layout)
self.setCentralWidget(container)
# Obține și afișează dependențele
self.display_dependencies()
def display_dependencies(self):
try:
# Rulează pipdeptree pentru a obține ierarhia dependențelor
result = subprocess.run(['pipdeptree', '--warn', 'silence'], capture_output=True, text=True)
dependencies = result.stdout.splitlines()
for line in dependencies:
# Determină nivelul de indentare pentru ierarhia dependențelor
indent_level = len(line) - len(line.lstrip())
dependency_name = line.strip()
# Creează un item pentru fiecare dependență
item = QTreeWidgetItem([dependency_name])
# Atribuie iconițe pe baza compatibilității (exemplu simplificat)
if "(*)" in dependency_name: # Exemplu de incompatibilitate (poți schimba după caz)
item.setIcon(0, self.style().standardIcon(QStyle.StandardPixmap.SP_DialogCancelButton))
item.setText(1, "Incompatible")
else:
item.setIcon(0, self.style().standardIcon(QStyle.StandardPixmap.SP_DialogApplyButton))
item.setText(1, "Compatible")
# Adaugă item-ul în arbore
if indent_level == 0:
self.tree_widget.addTopLevelItem(item)
else:
# Alege ultimul item părinte și adaugă dependența ca sub-item
parent_item = self.tree_widget.topLevelItem(self.tree_widget.topLevelItemCount() - 1)
parent_item.addChild(item)
# Extinde toate elementele din arbore
self.tree_widget.expandAll()
except Exception as e:
error_item = QTreeWidgetItem(["Error", str(e)])
error_item.setIcon(0, self.style().standardIcon(QStyle.StandardPixmap.SP_MessageBoxCritical))
self.tree_widget.addTopLevelItem(error_item)
if __name__ == "__main__":
from PyQt6.QtCore import Qt
app = QApplication(sys.argv)
viewer = DependencyViewer()
viewer.show()
sys.exit(app.exec())
pip install elevenlabs
Collecting elevenlabs
...
Installing collected packages: websockets, sniffio, pydantic-core, h11, annotated-types, pydantic, httpcore, anyio, httpx,
elevenlabs
Successfully installed annotated-types-0.7.0 anyio-4.8.0 elevenlabs-1.52.0 h11-0.14.0 httpcore-1.0.7 httpx-0.28.1
pydantic-2.10.6the official website pydantic-core-2.27.2 sniffio-1.3.1 websockets-15.0
...
pip install playsound
Collecting playsound
...
Installing collected packages: playsound
Successfully installed playsound-1.3.0
...
python elevenlabs_test_001.py
Fișierul audio a fost salvat la generated_audio.mp3
import io # Importarea bibliotecii io
from elevenlabs import ElevenLabs
from playsound import playsound
import tempfile
import os
# API Key pentru ElevenLabs
api_key = "API_KEY"
voice_id = "JBFqnCBsd6RMkjVDRZzb"
# Configurarea clientului ElevenLabs
client = ElevenLabs(api_key=api_key )
# Textul pe care vrei să-l convertești în audio
text = 'Hello! This is a test without mpv.'
# Generarea audio
audio_generator = client.generate(text=text, voice=voice_id)
# Colectarea datelor din generator într-un obiect BytesIO
audio_data = io.BytesIO()
for chunk in audio_generator:
audio_data.write(chunk)
audio_data.seek(0) # Resetarea pointerului la începutul streamului
# Specificarea căii de salvare pentru fișierul audio
save_path = 'generated_audio.mp3'
# Salvarea audio într-un fișier temporar
with tempfile.NamedTemporaryFile(delete=False, suffix='.mp3') as temp_audio:
temp_audio.write(audio_data.read())
temp_audio_path = temp_audio.name
# Redarea fișierului audio utilizând playsound
playsound(temp_audio_path)
# Salvarea fișierului audio generat într-o locație specificată
with open(save_path, 'wb') as f:
audio_data.seek(0) # Resetarea pointerului la începutul streamului pentru a citi din nou datele
f.write(audio_data.read())
print(f'Fișierul audio a fost salvat la {save_path}')
root@localhost:/home/mythcat# dnf5 install python3-opencv.x86_64
import sys
import cv2
import numpy as np
from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QLabel, QSlider, QFileDialog, QPushButton, QHBoxLayout
from PyQt6.QtGui import QImage, QPixmap
from PyQt6.QtCore import Qt, pyqtSlot
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Real-Time Color Selection")
self.setGeometry(100, 100, 1200, 800)
# Create central widget and main layout
central_widget = QWidget()
self.setCentralWidget(central_widget)
main_layout = QVBoxLayout(central_widget)
# Create image label
self.image_label = QLabel()
main_layout.addWidget(self.image_label)
# Initialize sliders
self.lower_h = QSlider(Qt.Orientation.Horizontal)
self.lower_s = QSlider(Qt.Orientation.Horizontal)
self.lower_v = QSlider(Qt.Orientation.Horizontal)
self.upper_h = QSlider(Qt.Orientation.Horizontal)
self.upper_s = QSlider(Qt.Orientation.Horizontal)
self.upper_v = QSlider(Qt.Orientation.Horizontal)
# Set slider ranges
for slider in [self.lower_h, self.upper_h]:
slider.setRange(0, 179)
for slider in [self.lower_s, self.lower_v, self.upper_s, self.upper_v]:
slider.setRange(0, 255)
# Set initial slider values
self.lower_h.setValue(50)
self.lower_s.setValue(100)
self.lower_v.setValue(50)
self.upper_h.setValue(130)
self.upper_s.setValue(255)
self.upper_v.setValue(255)
# Connect sliders to update function
self.lower_h.valueChanged.connect(self.update_hsv_range)
self.lower_s.valueChanged.connect(self.update_hsv_range)
self.lower_v.valueChanged.connect(self.update_hsv_range)
self.upper_h.valueChanged.connect(self.update_hsv_range)
self.upper_s.valueChanged.connect(self.update_hsv_range)
self.upper_v.valueChanged.connect(self.update_hsv_range)
# Create slider layouts with labels
sliders_layout = QVBoxLayout()
# Add slider pairs with labels
slider_pairs = [
("Lower Hue", self.lower_h),
("Lower Saturation", self.lower_s),
("Lower Value", self.lower_v),
("Upper Hue", self.upper_h),
("Upper Saturation", self.upper_s),
("Upper Value", self.upper_v)
]
for label_text, slider in slider_pairs:
row_layout = QHBoxLayout()
label = QLabel(label_text)
label.setMinimumWidth(120)
row_layout.addWidget(label)
row_layout.addWidget(slider)
sliders_layout.addLayout(row_layout)
main_layout.addLayout(sliders_layout)
# Add buttons
button_layout = QHBoxLayout()
self.reset_button = QPushButton("Reset Values")
self.reset_button.clicked.connect(self.reset_values)
button_layout.addWidget(self.reset_button)
self.open_image_button = QPushButton("Open Image")
self.open_image_button.clicked.connect(self.open_image)
button_layout.addWidget(self.open_image_button)
self.save_button = QPushButton("Save Image")
self.save_button.clicked.connect(self.save_image)
button_layout.addWidget(self.save_button)
main_layout.addLayout(button_layout)
# Process initial image
self.process_image()
def process_image(self):
image_bgr = cv2.imread("image.png")
if image_bgr is None:
image_bgr = cv2.imread("default_image.png")
self.image_bgr = image_bgr
self.image_hsv = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2HSV)
# Create initial mask using current slider values
lower_values = np.array([self.lower_h.value(), self.lower_s.value(), self.lower_v.value()])
upper_values = np.array([self.upper_h.value(), self.upper_s.value(), self.upper_v.value()])
mask_test = cv2.inRange(self.image_hsv, lower_values, upper_values)
image_bgr_masked = cv2.bitwise_and(image_bgr, image_bgr, mask=mask_test)
self.image_rgb = cv2.cvtColor(image_bgr_masked, cv2.COLOR_BGR2RGB)
self.update_image()
def update_image(self):
height, width, channel = self.image_rgb.shape
bytes_per_line = width * channel
q_image = QImage(self.image_rgb.data, width, height, bytes_per_line, QImage.Format.Format_RGB888)
pixmap = QPixmap.fromImage(q_image)
self.image_label.setPixmap(pixmap.scaled(700, 500, Qt.AspectRatioMode.KeepAspectRatio))
def update_hsv_range(self):
lower_values = np.array([self.lower_h.value(), self.lower_s.value(), self.lower_v.value()])
upper_values = np.array([self.upper_h.value(), self.upper_s.value(), self.upper_v.value()])
mask_test = cv2.inRange(self.image_hsv, lower_values, upper_values)
image_bgr_masked = cv2.bitwise_and(self.image_bgr, self.image_bgr, mask=mask_test)
self.image_rgb = cv2.cvtColor(image_bgr_masked, cv2.COLOR_BGR2RGB)
self.update_image()
def reset_values(self):
self.lower_h.setValue(50)
self.lower_s.setValue(100)
self.lower_v.setValue(50)
self.upper_h.setValue(130)
self.upper_s.setValue(255)
self.upper_v.setValue(255)
def open_image(self):
filename, _ = QFileDialog.getOpenFileName(self, "Select Image File", "", "Image Files (*.png *.jpg *.jpeg)")
if filename:
self.image_bgr = cv2.imread(filename)
if self.image_bgr is not None:
self.image_hsv = cv2.cvtColor(self.image_bgr, cv2.COLOR_BGR2HSV)
self.update_hsv_range() # This will apply current filter and update display
def save_image(self):
filename, _ = QFileDialog.getSaveFileName(self, "Save Image", "", "PNG Files (*.png);;JPEG Files (*.jpg)")
if filename:
# Make sure filename has an extension
if not filename.endswith(('.png', '.jpg', '.jpeg')):
filename += '.png'
# Convert and save
output_image = cv2.cvtColor(self.image_rgb, cv2.COLOR_RGB2BGR)
cv2.imwrite(filename, output_image)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
from PyQt6.QtWidgets import QApplication, QMainWindow, QTextEdit, QVBoxLayout, QHBoxLayout, QWidget, QPushButton, QCheckBox, QLineEdit, QLabel
from PyQt6.QtGui import QTextDocument
from PyQt6.QtCore import Qt
import re
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("HTML Cleaner")
self.text_edit = QTextEdit()
self.clean_button = QPushButton("Clean HTML")
self.transform_div_checkbox = QCheckBox("Transform tags")
self.realtime_checkbox = QCheckBox("Realtime")
self.regex_edit = QLineEdit()
self.regex_edit.setPlaceholderText("Enter regex pattern")
self.regex_edit.setEnabled(False) # Dezactivăm inițial
top_layout = QHBoxLayout()
top_layout.addWidget(self.clean_button)
top_layout.addWidget(self.transform_div_checkbox)
top_layout.addWidget(QLabel("Regex:"))
top_layout.addWidget(self.regex_edit)
top_layout.addWidget(self.realtime_checkbox)
main_layout = QVBoxLayout()
main_layout.addLayout(top_layout)
main_layout.addWidget(self.text_edit)
container = QWidget()
container.setLayout(main_layout)
self.setCentralWidget(container)
self.clean_button.clicked.connect(self.clean_html)
self.realtime_checkbox.stateChanged.connect(self.toggle_realtime)
self.regex_edit.textChanged.connect(self.realtime_update)
def clean_html(self):
html_text = self.text_edit.toPlainText()
clean_text = self.remove_html_tags(html_text)
self.text_edit.setPlainText(clean_text)
def remove_html_tags(self, text):
# Remove CSS
text = re.sub(r'.*?', '', text, flags=re.DOTALL)
# Remove JavaScript
text = re.sub(r'.*?', '', text, flags=re.DOTALL)
# Remove HTML comments
text = re.sub(r'', '', text, flags=re.DOTALL)
# Transform tags if checkbox is checked
if self.transform_div_checkbox.isChecked():
text = re.sub(r']*>', '', text)
# Remove HTML tags but keep content
clean = re.compile('<.*?>')
text = re.sub(clean, '', text)
# Remove empty lines
text = re.sub(r'\n\s*\n', '\n', text)
return text
def toggle_realtime(self):
if self.realtime_checkbox.isChecked():
self.regex_edit.setEnabled(True) # Activăm editbox-ul
self.text_edit.textChanged.connect(self.realtime_update)
else:
self.regex_edit.setEnabled(False) # Dezactivăm editbox-ul
self.text_edit.textChanged.disconnect(self.realtime_update)
def realtime_update(self):
if self.realtime_checkbox.isChecked():
html_text = self.text_edit.toPlainText()
regex_pattern = self.regex_edit.text()
if regex_pattern:
try:
html_text = re.sub(regex_pattern, '', html_text)
except re.error:
pass # Ignore regex errors
self.text_edit.blockSignals(True)
self.text_edit.setPlainText(html_text)
self.text_edit.blockSignals(False)
app = QApplication([])
window = MainWindow()
window.show()
app.exec()
Posted by
Cătălin George Feștilă
Labels:
2024,
module,
modules,
packages,
PyQt6,
python,
python 3,
python modules,
python packages,
re,
tutorial,
tutorials
pip install faker
Collecting faker
...
Installing collected packages: six, python-dateutil, faker
Successfully installed faker-28.1.0 python-dateutil-2.9.0.post0 six-1.16.0
pip install pandas
...
Successfully built pandas
Installing collected packages: pytz, tzdata, pandas
Successfully installed pandas-2.2.2 pytz-2024.1 tzdata-2024.1
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QTableView
from PyQt6.QtCore import Qt, QAbstractTableModel
import pandas as pd
from faker import Faker
# Generăm date false folosind Faker
fake = Faker()
data = {
'Name': [fake.name() for _ in range(100)],
'Address': [fake.address() for _ in range(100)],
'Email': [fake.email() for _ in range(100)],
'IP Address': [fake.ipv4() for _ in range(100)] # Adăugăm adresa IP
}
# Creăm un DataFrame Pandas
df = pd.DataFrame(data)
# Definim un model pentru QTableView
class PandasModel(QAbstractTableModel):
def __init__(self, df):
super().__init__()
self._df = df
def rowCount(self, parent=None):
return len(self._df)
def columnCount(self, parent=None):
return self._df.shape[1]
def data(self, index, role=Qt.ItemDataRole.DisplayRole):
if index.isValid():
if role == Qt.ItemDataRole.DisplayRole:
return str(self._df.iloc[index.row(), index.column()])
return None
def headerData(self, section, orientation, role=Qt.ItemDataRole.DisplayRole):
if role == Qt.ItemDataRole.DisplayRole:
if orientation == Qt.Orientation.Horizontal:
return self._df.columns[section]
else:
return str(section)
return None
# Aplicatia PyQt6
app = QApplication(sys.argv)
window = QMainWindow()
view = QTableView()
# Setăm modelul pentru QTableView
model = PandasModel(df)
view.setModel(model)
# Configurăm fereastra principală
window.setCentralWidget(view)
window.resize(800, 600)
window.show()
# Rulăm aplicația
sys.exit(app.exec())
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QSlider
from PyQt6.QtCore import Qt
class SliderWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Two Slideres")
self.setGeometry(100, 100, 640, 200)
layout = QVBoxLayout()
self.slider_max = QSlider(Qt.Orientation.Horizontal)
self.slider_max.setMinimum(0)
self.slider_max.setMaximum(100)
self.slider_max.setValue(100)
self.slider_max.valueChanged.connect(self.update_min_slider)
self.slider_min = QSlider(Qt.Orientation.Horizontal)
self.slider_min.setMinimum(0)
self.slider_min.setMaximum(100)
self.slider_min.setValue(0)
self.slider_min.valueChanged.connect(self.update_max_slider)
layout.addWidget(self.slider_max)
layout.addWidget(self.slider_min)
self.setLayout(layout)
def update_min_slider(self, value):
self.slider_min.blockSignals(True)
self.slider_min.setValue(100 - value)
self.slider_min.blockSignals(False)
def update_max_slider(self, value):
self.slider_max.blockSignals(True)
self.slider_max.setValue(100 - value)
self.slider_max.blockSignals(False)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = SliderWindow()
window.show()
sys.exit(app.exec())
pip install --upgrade setuptools
pip install msvc-runtime
ERROR: Could not find a version that satisfies the requirement msvc-runtime (from versions: none)
ERROR: No matching distribution found for msvc-runtime
pip install pyqt6
Collecting pyqt6
Using cached PyQt6-6.7.1-cp38-abi3-win_amd64.whl.metadata (2.1 kB)
...
Successfully built PyQt6-sip
Installing collected packages: PyQt6-Qt6, PyQt6-sip, pyqt6
Successfully installed PyQt6-Qt6-6.7.2 PyQt6-sip-13.8.0 pyqt6-6.7.1
#unittest.main()
import sys
from PyQt6.QtWidgets import QApplication, QDialog, QMainWindow, QPushButton
from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt6 import QtTest
# Unitest area
import unittest
from time import sleep
def sleep_sec(sec):
sleep(10*sec)
#
#define class for unittest
class Test(unittest.TestCase):
def test_square(self):
sleep_sec(5)
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(640, 480)
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
class Window(QMainWindow):
"""Main window."""
def __init__(self, parent=None):
"""Initializer."""
super().__init__(parent)
# Use a QPushButton for the central widget
self.centralWidget = QPushButton("Test_Button")
# Connect the .clicked() signal with the .onTest_BtnClicked() slot
self.centralWidget.clicked.connect(self.onTest_BtnClicked)
self.setCentralWidget(self.centralWidget)
# Create a slot for launching the Test_ dialog
def onTest_BtnClicked(self):
"""Launch the Test_ dialog."""
dlg = Test_Dlg(self)
# This will test with QtTest just for click
QtTest.QTest.qWait(2500)
dlg.exec()
class Test_Dlg(QDialog):
"""Test dialog."""
def __init__(self, parent=None):
super().__init__(parent)
# Create an instance of the GUI
self.ui = Ui_Dialog()
# Run the .setupUi() method to show the GUI
self.ui.setupUi(self)
if __name__ == "__main__":
# this test all run of application and show :
# Ran 1 test in 50.001s
# uncoment this
#unittest.main()
# Create the application
app = QApplication(sys.argv)
# Create and show the application's main window
win = Window()
win.show()
# Run the application's main loop
sys.exit(app.exec())
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QTableView
from PyQt6.QtSql import QSqlDatabase, QSqlQuery, QSqlTableModel
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
# Initialize the database
self.init_db()
# Set up the GUI
self.table_view = QTableView(self)
self.setCentralWidget(self.table_view)
# Set up the model and connect it to the database
self.model = QSqlTableModel(self)
self.model.setTable('files')
self.model.select()
self.table_view.setModel(self.model)
def init_db(self):
# Connect to the database
db = QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('file_paths.db')
if not db.open():
print('Could not open database')
sys.exit(1)
def create_table(self):
# Create the 'files' table if it doesn't exist
query = QSqlQuery()
query.exec('CREATE TABLE IF NOT EXISTS files (id INTEGER PRIMARY KEY, path TEXT)')
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton, QProgressBar, QDialog, QComboBox, QLabel, QMessageBox
from PyQt6.QtGui import QIcon, QPixmap
from pytube import YouTube
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QDialogButtonBox
class FormatChecker:
def __init__(self, url):
self.url = url
def check_formats(self):
try:
yt = YouTube(self.url)
formats = []
streams = yt.streams.filter(only_video=True)
for stream in streams:
if stream.url:
format_info = {
'resolution': stream.resolution,
'file_extension': stream.mime_type.split("/")[-1]
}
formats.append(format_info)
print(" format_info ",format_info)
return formats
except Exception as e:
print("Error:", str(e))
return []
class FormatInfo:
def __init__(self, resolution, file_formats):
self.resolution = resolution
self.file_formats = file_formats
class ResolutionDialog(QDialog):
def __init__(self, formats, parent=None):
super().__init__(parent)
self.setWindowTitle("Select Resolution and File Format")
self.formats = formats
layout = QVBoxLayout(self)
self.resolution_combo = QComboBox(self)
for format_info in formats:
resolution = format_info.resolution
self.resolution_combo.addItem(resolution)
layout.addWidget(self.resolution_combo)
self.file_format_combo = QComboBox(self)
self.update_file_formats(self.resolution_combo.currentText())
layout.addWidget(self.file_format_combo)
button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
layout.addWidget(button_box)
self.resolution_combo.currentIndexChanged.connect(self.on_resolution_changed)
def update_file_formats(self, resolution):
self.file_format_combo.clear()
for format_info in self.formats:
if format_info.resolution == resolution:
file_formats = format_info.file_formats
self.file_format_combo.addItems(file_formats)
def selected_resolution(self):
return self.resolution_combo.currentText()
def selected_file_format(self):
return self.file_format_combo.currentText()
def on_resolution_changed(self, index):
resolution = self.resolution_combo.currentText()
self.update_file_formats(resolution)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("YouTube Downloader - selected - only_video =True")
self.setFixedWidth(640)
central_widget = QWidget(self)
self.setCentralWidget(central_widget)
layout = QVBoxLayout(central_widget)
self.url_edit = QLineEdit()
layout.addWidget(self.url_edit)
download_button = QPushButton("Download")
download_button.clicked.connect(self.show_resolution_dialog)
layout.addWidget(download_button)
progress_layout = QHBoxLayout()
layout.addLayout(progress_layout)
self.progress_bar = QProgressBar()
self.progress_bar.setTextVisible(True)
progress_layout.addWidget(self.progress_bar)
self.progress_icon_label = QLabel(self)
pixmap = QPixmap("youtube.png") # Înlocuiți "path_to_icon.png" cu calea către iconul dorit
self.progress_icon_label.setPixmap(pixmap)
progress_layout.addWidget(self.progress_icon_label)
def show_resolution_dialog(self):
url = self.url_edit.text()
if url:
format_checker = FormatChecker(url)
formats = format_checker.check_formats()
format_infos = []
for format in formats:
resolution = format['resolution']
file_extension = format['file_extension']
format_info = next((info for info in format_infos if info.resolution == resolution), None)
if format_info:
format_info.file_formats.append(file_extension)
else:
format_info = FormatInfo(resolution, [file_extension])
format_infos.append(format_info)
dialog = ResolutionDialog(format_infos, self)
if dialog.exec() == QDialog.DialogCode.Accepted:
resolution = dialog.selected_resolution()
file_format = dialog.selected_file_format()
self.download_video(url, resolution, file_format)
else:
print("Please enter a valid YouTube URL.")
def download_video(self, url, resolution, file_format):
try:
yt = YouTube(url)
stream = yt.streams.filter(only_video=True, resolution=resolution, mime_type="video/" + file_format).first()
if stream:
stream.download()
print("Download completed!")
QMessageBox.question(self, "Download Completed", "The video has been downloaded successfully.", QMessageBox.StandardButton.Ok)
else:
print("Error: The selected video format is not available for download.")
QMessageBox.question(self, "Download Error", "The selected video format is not available for download.", QMessageBox.StandardButton.Ok)
except Exception as e:
print("Error:", str(e))
QMessageBox.question(self, "Download Error", "An error occurred during the download.", QMessageBox.StandardButton.Ok)
def main():
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()