Refactored code to be more maintainable

This commit is contained in:
2024-07-13 17:58:27 +02:00
parent 1183327e7e
commit 901daf6c06
12 changed files with 355 additions and 437 deletions

2
.gitignore vendored
View File

@@ -1,4 +1,4 @@
/config.enc
config.enc
/__pycache__
*/__pycache__
/build

30
config/decrypt_config.py Normal file
View File

@@ -0,0 +1,30 @@
from cryptography.fernet import Fernet
import json
import os
class ConfigDecryptor:
def __init__(self, key):
self.key = key
def decrypt(self):
if not os.path.exists("config.enc"):
raise FileNotFoundError("The encrypted configuration file 'config.enc' does not exist.")
fernet = Fernet(self.key)
with open("config.enc", "rb") as encrypted_file:
encrypted = encrypted_file.read()
decrypted = fernet.decrypt(encrypted).decode()
return json.loads(decrypted)
# Define your key here
key = b'u4xTBY5Ns4WYdLvqMjEr138mpMmDEhhqTszKCcDy2cI=' # Replace with your actual key
if __name__ == "__main__":
key = b'u4xTBY5Ns4WYdLvqMjEr138mpMmDEhhqTszKCcDy2cI=' # Replace with your actual key
decryptor = ConfigDecryptor(key)
try:
config = decryptor.decrypt()
print(config)
except FileNotFoundError as e:
print(e)
except Exception as e:
print(f"An error occurred: {e}")

28
config/encrypt_config.py Normal file
View File

@@ -0,0 +1,28 @@
from cryptography.fernet import Fernet
class ConfigEncryptor:
def __init__(self):
self.key = Fernet.generate_key()
def encrypt_config(self, data):
fernet = Fernet(self.key)
encrypted = fernet.encrypt(data.encode())
with open("config.enc", "wb") as encrypted_file:
encrypted_file.write(encrypted)
def get_key(self):
return self.key.decode()
if __name__ == "__main__":
config_data = """
{
"url": "https://yourstore.com",
"consumer_key": "ck_yourconsumerkey",
"consumer_secret": "cs_yoursecret",
"username": "yourusername",
"password": "yourpassword"
}
"""
encryptor = ConfigEncryptor()
print(f"Encryption key: {encryptor.get_key()}")
encryptor.encrypt_config(config_data)

View File

@@ -1,25 +0,0 @@
from cryptography.fernet import Fernet
import json
import os
# Hardcoded key (replace with your generated key)
key = b'u4xTBY5Ns4WYdLvqMjEr138mpMmDEhhqTszKCcDy2cI='
def decrypt_config(key):
if not os.path.exists("config.enc"):
raise FileNotFoundError("The encrypted configuration file 'config.enc' does not exist.")
fernet = Fernet(key)
with open("config.enc", "rb") as encrypted_file:
encrypted = encrypted_file.read()
decrypted = fernet.decrypt(encrypted).decode()
return json.loads(decrypted)
if __name__ == "__main__":
try:
config = decrypt_config(key)
print(config) # Use the decrypted config
except FileNotFoundError as e:
print(e)
except Exception as e:
print(f"An error occurred: {e}")

View File

@@ -1,22 +0,0 @@
from cryptography.fernet import Fernet
# Generate a key and print it
key = Fernet.generate_key()
print(f"Encryption key: {key.decode()}") # Save this key securely
# Function to encrypt the configuration data
def encrypt_config(data, key):
fernet = Fernet(key)
encrypted = fernet.encrypt(data.encode())
with open("config.enc", "wb") as encrypted_file:
encrypted_file.write(encrypted)
if __name__ == "__main__":
config_data = """{
"url": "https://yourstore.com",
"consumer_key": "ck_yourconsumerkey",
"consumer_secret": "cs_yoursecret",
"username": "yourusername",
"password": "yourpassword"
}"""
encrypt_config(config_data, key)

70
main.py
View File

@@ -1,47 +1,47 @@
import tkinter as tk
from tkinter import ttk
from ui.local_processing_tab import create_tab_local
from ui.settings_tab import create_tab_settings
from ui.log_window import LogWindow
from ui.local_processing_tab import LocalProcessingTab
from ui.settings_tab import SettingsTab
from config.decrypt_config import ConfigDecryptor, key
class ImageProcessorApp:
def __init__(self, root):
self.root = root
self.root.title("Image Processor")
self.root.geometry("700x400")
from decrypt_config import decrypt_config, key
self.tab_parent = ttk.Notebook(self.root)
self.log_window = None
try:
config = decrypt_config(key)
wc_url = config['url']
wc_consumer_key = config['consumer_key']
wc_consumer_secret = config['consumer_secret']
wp_username = config['username']
wp_password = config['password']
self.local_processing_tab = LocalProcessingTab(self.tab_parent, "Local Processing", self.open_log_window)
self.settings_tab = SettingsTab(self.tab_parent, "Settings")
# Now use these variables to create your WooCommerce API instance
self.tab_parent.pack(expand=True, fill='both')
except FileNotFoundError as e:
print(e)
# Handle the missing file case, e.g., by prompting the user to create it
except Exception as e:
print(f"An error occurred: {e}")
# Handle other potential errors
log_window = None
def open_log_window(self):
if self.log_window is None or not self.log_window.winfo_exists():
self.log_window = LogWindow(self.root)
else:
self.log_window.lift()
def open_log_window():
global log_window
if log_window is None or not log_window.winfo_exists():
log_window = LogWindow(window)
else:
log_window.lift()
def run(self):
self.root.mainloop()
if __name__ == "__main__":
window = tk.Tk()
window.title("Image Processor")
window.geometry("700x400")
try:
decryptor = ConfigDecryptor(key)
config = decryptor.decrypt()
wc_url = config['url']
wc_consumer_key = config['consumer_key']
wc_consumer_secret = config['consumer_secret']
wp_username = config['username']
wp_password = config['password']
except FileNotFoundError as e:
print(f"File not found: {e}")
except Exception as e:
print(f"An error occurred: {e}")
tab_parent = ttk.Notebook(window)
create_tab_local(tab_parent, "Local Processing", open_log_window)
create_tab_settings(tab_parent, "Settings")
tab_parent.pack(expand=True, fill='both')
window.mainloop()
root = tk.Tk()
app = ImageProcessorApp(root)
app.run()

133
readme.md
View File

@@ -1,59 +1,48 @@
Image Processing Application
This application is a graphical user interface (GUI) tool designed for processing images either from a local directory or from a WooCommerce product catalog. It supports resizing images, renaming them based on customizable templates, and uploading them to a WooCommerce site.
Features
Resize images to specified dimensions.
Rename images using customizable templates with placeholders for various attributes.
Upload processed images to WooCommerce.
Process images from a local directory or WooCommerce products.
Image Processing Application Documentation
Overview
This Image Processing Application provides a GUI for selecting directories containing image files, setting canvas sizes, adding suffixes to filenames, and processing images. It logs all found images, displays how many images were found, and provides previews of the first image before and after processing.
Prerequisites
Python 3.10 or later
Required Python Packages
You can install the required packages using pip:
Python 3.10+: Ensure Python is installed on your machine.
Tkinter: This should come with Python, but ensure it's installed.
Pillow: For image handling. Install via pip:
sh
pip install -r requirements.txt
pip install pillow
ImageMagick
Additional Libraries: Ensure you have any additional libraries your utility functions (file_operations, image_processing) depend on.
ImageMagick is required for image processing. You can download and install it from ImageMagick's official website.
Application Setup
WooCommerce API Credentials
You need to have WooCommerce API credentials to interact with the WooCommerce site. These include the URL, consumer key, consumer secret, username, and password.
Setting Up
Clone the Repository
Clone this repository to your local machine:
Install Required Packages:
sh
git clone https://github.com/your-username/image-processing-app.git
cd image-processing-app
pip install pillow
Install Dependencies
Directory Structure:
Ensure your project directory looks something like this:
Install the required Python packages:
arduino
sh
image-processor/
├── ui/
│ └── local_processing_tab.py
├── utils/
│ ├── file_operations.py
│ └── image_processing.py
└── main.py
pip install -r requirements.txt
Configure WooCommerce API Credentials
Run the application and navigate to the Settings tab to enter and save your WooCommerce API credentials.
Script Files:
main.py: The main entry point of the application containing the script provided above.
file_operations.py: Contains browse_directory and other directory-related utility functions.
image_processing.py: Contains set_canvas_size and other image processing utility functions.
Running the Application
Run the main application script:
To run the application, navigate to the project directory and execute:
sh
@@ -61,75 +50,23 @@ python main.py
Creating an Executable
To create a standalone executable from this project, you can use PyInstaller. Follow the steps below:
To create an executable for this application, you can use pyinstaller. Follow the steps below:
Install PyInstaller
You can install PyInstaller using pip:
Install PyInstaller:
sh
pip install pyinstaller
Generate the Executable
Navigate to the project directory and run PyInstaller:
Create the Executable:
Navigate to the directory containing your main.py script and run:
sh
pyinstaller --onefile --noconsole main.py
pyinstaller --onefile --windowed main.py
Find the Executable
--onefile: Packages everything into a single executable file.
--windowed: Ensures the console window does not appear when running the GUI application.
After PyInstaller finishes, you can find the executable in the dist directory.
File Structure
main.py: Entry point for the application.
api/: Contains the woocommerce.py file for interacting with WooCommerce API.
utils/: Contains utility scripts for file operations and image processing.
ui/: Contains the UI components for the application.
config.enc: Encrypted file storing WooCommerce API credentials.
Requirements
Create a requirements.txt file with the following content:
tk
Pillow
requests
woocommerce
cryptography
pyinstaller
Usage
Select Source Type
Choose between local directory and WooCommerce product.
Set Canvas Size
Specify the dimensions to resize the images.
Filename Template
Define a template for renaming the images using placeholders like {name}, {sku}, {width}, {height}.
Start Processing
Click the "Start Processing" button to process the images. The log will appear in a separate window.
Notes
Ensure ImageMagick is correctly installed and added to your system's PATH.
The application uses the cryptography library to encrypt WooCommerce API credentials for security.
Support
If you encounter any issues or have questions, feel free to open an issue in the repository or contact the maintainer.
License
This project is licensed under the MIT License.
Acknowledgements
ImageMagick
WooCommerce
With this information, you should be able to set up, run, and create an executable for the Image Processing Application. Enjoy processing your images with ease!
Locate the Executable:
After running the command, you will find the executable in the dist folder within your project directory.

View File

@@ -1,7 +1,6 @@
import tkinter as tk
from tkinter import ttk
from tkinter.scrolledtext import ScrolledText
from tkinter import filedialog
from PIL import Image, ImageTk
import tempfile
import os
@@ -9,196 +8,161 @@ from utils.file_operations import browse_directory, process_directory_with_loggi
from utils.image_processing import set_canvas_size, resize_image
from api.woocommerce import process_product_images, process_all_products
class LocalProcessingTab:
def __init__(self, tab_parent, text, log):
self.log = log
self.tab = ttk.Frame(tab_parent)
tab_parent.add(self.tab, text=text)
canvas_width = 900
canvas_height = 900
self.log_window = None
self.create_log_window()
self.canvas_width = 900
self.canvas_height = 900
def create_tab_local(tab_parent, text, log):
tab = ttk.Frame(tab_parent)
tab_parent.add(tab, text=text)
self.source_type = tk.StringVar(value="local")
self.checkbox_var = tk.BooleanVar(value=False)
log_window = None
self.setup_ui()
self.update_source_fields()
def create_log_window():
nonlocal log_window
if log_window and tk.Toplevel.winfo_exists(log_window):
def create_log_window(self):
if self.log_window and tk.Toplevel.winfo_exists(self.log_window):
return
log_window = tk.Toplevel()
log_window.title("Processing Log")
log_text = ScrolledText(log_window, state='disabled', wrap='word', height=20, width=80)
log_text.pack(expand=True, fill='both')
self.log_window = tk.Toplevel()
self.log_window.title("Processing Log")
self.log_text = ScrolledText(self.log_window, state='disabled', wrap='word', height=20, width=80)
self.log_text.pack(expand=True, fill='both')
def log_message(message):
log_text.config(state='normal')
log_text.insert(tk.END, message + "\n")
log_text.see(tk.END)
log_text.config(state='disabled')
log_text.update_idletasks() # Ensure the GUI updates
return log_message
def log_message(self, message):
self.log_text.config(state='normal')
self.log_text.insert(tk.END, message + "\n")
self.log_text.see(tk.END)
self.log_text.config(state='disabled')
self.log_text.update_idletasks()
# Source selection section
source_label = tk.Label(tab, text="Source Type:")
source_label.grid(row=0, column=0, padx=5, pady=5, sticky='w')
def setup_ui(self):
source_type = tk.StringVar(value="local")
source_dropdown = ttk.Combobox(tab, textvariable=source_type, values=["local", "product", "all_products"], state="readonly")
source_dropdown.grid(row=1, column=0, padx=5, pady=5, sticky='w')
source_dropdown.bind("<<ComboboxSelected>>", lambda e: update_source_fields())
# Source selection section
self.source_label = tk.Label(self.tab, text="Source Type:")
self.source_label.grid(row=0, column=0, padx=5, pady=5, sticky='w')
# Local Directory selection section
def update_directory():
directory = browse_directory()
if directory:
# Show only the last directory name with ../
truncated_directory = f"../{os.path.basename(directory)}"
button_browse.config(text=truncated_directory)
update_previews()
self.source_type = tk.StringVar(value="local")
self.source_dropdown = ttk.Combobox(self.tab, textvariable=self.source_type, values=["local", "product", "all_products"], state="readonly")
self.source_dropdown.grid(row=1, column=0, padx=5, pady=5, sticky='w')
self.source_dropdown.bind("<<ComboboxSelected>>", lambda e: self.update_source_fields())
button_browse = tk.Button(tab, text="Browse", command=update_directory)
button_browse.grid(row=2, column=0, padx=5, pady=5, sticky='nw')
self.browse_button = ttk.Button(self.tab, text="Browse", command=self.browse_directory_command)
self.browse_button.grid(row=2, column=0, padx=5, pady=5, sticky='w')
# WooCommerce Product ID section
product_id_label = tk.Label(tab, text="Product ID:")
product_id_label.grid(row=2, column=0, padx=5, pady=5, sticky='w')
# WooCommerce Product ID section
self.product_id_label = tk.Label(self.tab, text="Product ID:")
self.product_id_label.grid(row=2, column=0, padx=5, pady=5, sticky='w')
product_id_entry = tk.Entry(tab)
product_id_entry.grid(row=3, column=0, padx=5, pady=5, sticky='w')
# SKU section
additional_name_label = tk.Label(tab, text="Add suffix:")
additional_name_label.grid(row=3, column=1, padx=5, pady=5, sticky='w')
self.product_id_entry = tk.Entry(self.tab)
self.product_id_entry.grid(row=3, column=0, padx=5, pady=5, sticky='w')
additional_name_entry = tk.Entry(tab)
additional_name_entry.grid(row=3, column=2, padx=5, pady=5, sticky='w')
# SKU section
self.additional_name_label = tk.Label(self.tab, text="Add suffix:")
self.additional_name_label.grid(row=3, column=1, padx=5, pady=5, sticky='w')
# Template section
template_label = tk.Label(tab, text="Filename Template:")
template_label.grid(row=3, column=1, padx=5, pady=5, sticky='w')
self.additional_name_entry = tk.Entry(self.tab)
self.additional_name_entry.grid(row=3, column=2, padx=5, pady=5, sticky='w')
template_entry = tk.Entry(tab)
template_entry.insert(0, "{slug}_{sku}_{width}x{height}")
template_entry.grid(row=3, column=2, padx=5, columnspan=2, pady=5, sticky='w')
# Template section
self.template_label = tk.Label(self.tab, text="Filename Template:")
self.template_label.grid(row=3, column=1, padx=5, pady=5, sticky='w')
self.template_entry = tk.Entry(self.tab)
self.template_entry.insert(0, "{slug}_{sku}_{width}x{height}")
self.template_entry.grid(row=3, column=2, padx=5, columnspan=2, pady=5, sticky='w')
# Canvas size section
width_label = tk.Label(self.tab, text="Canvas Width:")
width_label.grid(row=0, column=1, padx=5, pady=5, sticky='w')
self.width_entry = tk.Entry(self.tab)
self.width_entry.insert(0, "900")
self.width_entry.grid(row=0, column=2, padx=5, pady=5, sticky='w')
self.height_label = tk.Label(self.tab, text="Canvas Height:")
self.height_label.grid(row=1, column=1, padx=5, pady=5, sticky='w')
self.height_entry = tk.Entry(self.tab)
self.height_entry.insert(0, "900")
self.height_entry.grid(row=1, column=2, padx=5, pady=5, sticky='w')
self.button_set_size = tk.Button(self.tab, text="Save Size", command=self.apply_canvas_size)
self.button_set_size.grid(row=2, column=1, columnspan=2, padx=5, pady=5, sticky='w')
# Checkbox for deleting images
self.checkbox_var = tk.BooleanVar()
self.checkbox = tk.Checkbutton(self.tab, text="Delete image when done", variable=self.checkbox_var)
self.checkbox.grid(row=0, column=3, columnspan=2, padx=5, pady=5, sticky='w')
self.button_start = tk.Button(self.tab, text="Start Processing", command=self.start_processing)
self.button_start.grid(row=1, column=3, columnspan=2, padx=5, pady=5, sticky='w')
# Image previews
self.before_label = tk.Label(self.tab, text="Before:")
self.before_label.grid(row=5, column=0, padx=5, pady=5, sticky='w')
self.before_image_label = tk.Label(self.tab)
self.before_image_label.grid(row=6, column=0, padx=5, pady=5, sticky='w')
self.after_label = tk.Label(self.tab, text="After:")
self.after_label.grid(row=5, column=1, padx=5, pady=5, sticky='w')
self.after_image_label = tk.Label(self.tab)
self.after_image_label.grid(row=6, column=1, padx=5, pady=5, sticky='w')
def update_source_fields():
print(source_type.get())
if source_type.get() == "local":
button_browse.grid()
product_id_label.grid_remove()
product_id_entry.grid_remove()
additional_name_label.grid()
additional_name_entry.grid()
template_entry.grid_remove()
template_label.grid_remove()
elif source_type.get() == "product":
button_browse.grid_remove()
product_id_label.grid()
product_id_entry.grid()
additional_name_label.grid_remove()
additional_name_entry.grid_remove()
def update_source_fields(self):
source = self.source_type.get()
if source == "local":
self.browse_button.grid()
self.product_id_label.grid_remove()
self.product_id_entry.grid_remove()
self.update_previews()
else:
button_browse.grid_remove()
product_id_label.grid_remove()
product_id_entry.grid_remove()
product_id_label.grid()
product_id_entry.grid()
additional_name_label.grid_remove()
additional_name_entry.grid_remove()
self.browse_button.grid_remove()
self.product_id_label.grid()
self.product_id_entry.grid()
update_source_fields() # Initial call to set correct fields
# Canvas size section
width_label = tk.Label(tab, text="Canvas Width:")
width_label.grid(row=0, column=1, padx=5, pady=5, sticky='w')
width_entry = tk.Entry(tab)
width_entry.insert(0, "900")
width_entry.grid(row=0, column=2, padx=5, pady=5, sticky='w')
height_label = tk.Label(tab, text="Canvas Height:")
height_label.grid(row=1, column=1, padx=5, pady=5, sticky='w')
height_entry = tk.Entry(tab)
height_entry.insert(0, "900")
height_entry.grid(row=1, column=2, padx=5, pady=5, sticky='w')
def apply_canvas_size():
global canvas_width, canvas_height
canvas_width = int(width_entry.get())
canvas_height = int(height_entry.get())
set_canvas_size(canvas_width, canvas_height)
update_previews()
button_set_size = tk.Button(tab, text="Save Size", command=apply_canvas_size)
button_set_size.grid(row=2, column=1, columnspan=2, padx=5, pady=5, sticky='w')
# Checkbox for deleting images
checkbox_var = tk.BooleanVar()
checkbox = tk.Checkbutton(tab, text="Delete image when done", variable=checkbox_var)
checkbox.grid(row=0, column=3, columnspan=2, padx=5, pady=5, sticky='w')
# Start Processing button
def start_processing():
log_message = None # create_log_window()
if source_type.get() == "local":
process_directory_with_logging(additional_name_entry.get(), checkbox_var.get(), log_message, update_previews)
elif source_type.get() == "product":
product_id = product_id_entry.get()
process_product_images(product_id, template_entry.get(), canvas_width, canvas_height)
else:
process_all_products(template_entry.get(), canvas_width, canvas_height)
button_start = tk.Button(tab, text="Start Processing", command=start_processing)
button_start.grid(row=1, column=3, columnspan=2, padx=5, pady=5, sticky='w')
# Image previews
before_label = tk.Label(tab, text="Before:")
before_label.grid(row=5, column=0, columnspan=2, padx=5, pady=5, sticky='w')
before_image_label = tk.Label(tab)
before_image_label.grid(row=6, columnspan=2, column=0, padx=5, pady=5, sticky='w')
after_label = tk.Label(tab, text="After:")
after_label.grid(row=5, columnspan=2, column=2, padx=5, pady=5, sticky='w')
after_image_label = tk.Label(tab)
after_image_label.grid(row=6, columnspan=2, column=2, padx=5, pady=5, sticky='w')
def update_previews(before_path=None, after_path=None):
def update_previews(self, before_path=None, after_path=None):
if before_path and after_path:
before_img = Image.open(before_path)
before_img.thumbnail((150, 150))
before_photo = ImageTk.PhotoImage(before_img)
before_image_label.config(image=before_photo)
before_image_label.image = before_photo
after_img = Image.open(after_path)
after_img.thumbnail((150, 150))
after_photo = ImageTk.PhotoImage(after_img)
after_image_label.config(image=after_photo)
after_image_label.image = after_photo
self.set_image_preview(before_path, self.before_image_label)
self.set_image_preview(after_path, self.after_image_label)
else:
first_image_path = get_first_image_path()
if first_image_path:
with tempfile.NamedTemporaryFile(suffix='.jpg', delete=False) as temp_file:
output_path = temp_file.name
resize_image(first_image_path, output_path, additional_name_entry.get())
before_img = Image.open(first_image_path)
before_img.thumbnail((150, 150))
before_photo = ImageTk.PhotoImage(before_img)
before_image_label.config(image=before_photo)
before_image_label.image = before_photo
self.set_image_preview(first_image_path, self.before_image_label)
self.after_image_label.config(image='')
after_img = Image.open(output_path)
after_img.thumbnail((150, 150))
after_photo = ImageTk.PhotoImage(after_img)
after_image_label.config(image=after_photo)
after_image_label.image = after_photo
def set_image_preview(self, image_path, label):
img = Image.open(image_path)
img.thumbnail((150, 150))
photo = ImageTk.PhotoImage(img)
label.config(image=photo)
label.image = photo
# Configure column weights to allow the log_text to expand
tab.columnconfigure(0, weight=1)
tab.columnconfigure(1, weight=1)
tab.columnconfigure(2, weight=1)
tab.columnconfigure(3, weight=1)
tab.rowconfigure(6, weight=1)
def browse_directory_command(self):
directory = browse_directory()
if directory:
self.browse_button.config(text=directory)
self.update_previews()
def apply_canvas_size(self):
self.canvas_width = int(self.width_entry.get())
self.canvas_height = int(self.height_entry.get())
set_canvas_size(self.canvas_width, self.canvas_height)
self.update_previews()
def start_processing(self):
source = self.source_type.get()
print(self.checkbox_var.get())
if source == "local":
process_directory_with_logging(self.browse_button.cget("text"), self.additional_name_entry.get(), self.checkbox_var.get(), self.log_message, self.update_previews)
elif source == "product":
process_product_images(self.product_id_entry.get(), self.canvas_width, self.canvas_height, self.log_message)
elif source == "all_products":
process_all_products(self.canvas_width, self.canvas_height, self.log_message)
self.update_previews()

View File

@@ -1,16 +1,17 @@
import tkinter as tk
from tkinter.scrolledtext import ScrolledText
from tkinter import Toplevel, Text
class LogWindow(tk.Toplevel):
def __init__(self, parent):
super().__init__(parent)
self.title("Processing Log")
self.geometry("600x400")
self.log_text = ScrolledText(self, state='disabled', wrap='word')
self.log_text.pack(expand=True, fill='both')
class LogWindow(Toplevel):
def __init__(self, master=None, **kwargs):
super().__init__(master, **kwargs)
self.title("Log Window")
self.geometry("500x300")
self.text = Text(self)
self.text.pack(expand=True, fill='both')
self.protocol("WM_DELETE_WINDOW", self.hide)
def log(self, message):
self.log_text.config(state='normal')
self.log_text.insert(tk.END, message + "\n")
self.log_text.see(tk.END)
self.log_text.config(state='disabled')
self.text.insert('end', message + '\n')
self.text.see('end')
def hide(self):
self.withdraw()

View File

@@ -2,57 +2,58 @@ import tkinter as tk
from tkinter import ttk
from api.woocommerce import save_credentials, load_credentials
def create_tab_settings(tab_parent, text):
tab = ttk.Frame(tab_parent)
tab_parent.add(tab, text=text)
class SettingsTab:
def __init__(self, tab_parent, text):
self.tab = ttk.Frame(tab_parent)
tab_parent.add(self.tab, text=text)
credentials = load_credentials()
url_value = credentials['url'] if credentials else ''
consumer_key_value = credentials['consumer_key'] if credentials else ''
consumer_secret_value = credentials['consumer_secret'] if credentials else ''
username_value = credentials['username'] if credentials else ''
password_value = credentials['password'] if credentials else ''
self.credentials = load_credentials()
self.setup_ui()
url_label = tk.Label(tab, text="WooCommerce URL:")
url_label.pack(pady=5)
def setup_ui(self):
url_label = tk.Label(self.tab, text="WooCommerce URL:")
url_label.pack(pady=5)
url_entry = tk.Entry(tab)
url_entry.insert(0, url_value)
url_entry.pack()
self.url_entry = tk.Entry(self.tab)
self.url_entry.insert(0, self.credentials.get('url', ''))
self.url_entry.pack(pady=5)
consumer_key_label = tk.Label(tab, text="Consumer Key:")
consumer_key_label.pack(pady=5)
consumer_key_label = tk.Label(self.tab, text="Consumer Key:")
consumer_key_label.pack(pady=5)
consumer_key_entry = tk.Entry(tab)
consumer_key_entry.insert(0, consumer_key_value)
consumer_key_entry.pack()
self.consumer_key_entry = tk.Entry(self.tab)
self.consumer_key_entry.insert(0, self.credentials.get('consumer_key', ''))
self.consumer_key_entry.pack(pady=5)
consumer_secret_label = tk.Label(tab, text="Consumer Secret:")
consumer_secret_label.pack(pady=5)
consumer_secret_label = tk.Label(self.tab, text="Consumer Secret:")
consumer_secret_label.pack(pady=5)
consumer_secret_entry = tk.Entry(tab, show="*")
consumer_secret_entry.insert(0, consumer_secret_value)
consumer_secret_entry.pack()
self.consumer_secret_entry = tk.Entry(self.tab, show="*")
self.consumer_secret_entry.insert(0, self.credentials.get('consumer_secret', ''))
self.consumer_secret_entry.pack(pady=5)
username_label = tk.Label(tab, text="Username:")
username_label.pack(pady=5)
username_label = tk.Label(self.tab, text="Username:")
username_label.pack(pady=5)
username_entry = tk.Entry(tab)
username_entry.insert(0, username_value)
username_entry.pack()
self.username_entry = tk.Entry(self.tab)
self.username_entry.insert(0, self.credentials.get('username', ''))
self.username_entry.pack(pady=5)
password_label = tk.Label(tab, text="Password:")
password_label.pack(pady=5)
password_label = tk.Label(self.tab, text="Password:")
password_label.pack(pady=5)
password_entry = tk.Entry(tab, show="*")
password_entry.insert(0, password_value)
password_entry.pack()
self.password_entry = tk.Entry(self.tab, show="*")
self.password_entry.insert(0, self.credentials.get('password', ''))
self.password_entry.pack(pady=5)
button_save = tk.Button(tab, text="Save Credentials", command=lambda: save_credentials(
url_entry.get(),
consumer_key_entry.get(),
consumer_secret_entry.get(),
username_entry.get(),
password_entry.get()
))
button_save.pack(pady=5)
save_button = tk.Button(self.tab, text="Save Credentials", command=self.save_credentials)
save_button.pack(pady=5)
def save_credentials(self):
save_credentials(
self.url_entry.get(),
self.consumer_key_entry.get(),
self.consumer_secret_entry.get(),
self.username_entry.get(),
self.password_entry.get()
)

View File

@@ -23,7 +23,8 @@ def get_first_image_path():
return os.path.join(root, file)
return None
def process_directory_with_logging(additional_name, is_checked, log, update_previews):
def process_directory_with_logging(selected_directory: str, additional_name: str = '', is_checked: bool = False, log = None, update_previews = None):
print(f"is_checked: {is_checked}")
if not selected_directory:
messagebox.showwarning("No Directory", "Please select a directory.")
return
@@ -56,12 +57,9 @@ def process_directory_with_logging(additional_name, is_checked, log, update_prev
os.makedirs(os.path.dirname(output_path), exist_ok=True)
resize_image(file_path, output_path, additional_name)
# with tempfile.NamedTemporaryFile(suffix='.jpg', delete=False) as temp_file:
# temp_output_path = temp_file.name
# resize_image(file_path, temp_output_path, additional_name)
# update_previews(file_path, temp_output_path)
if os.path.exists(file_path) and is_checked:
if log:
log(f"removing: {file_path}")
os.remove(file_path)
if log:
log(f"Processed: {file_path}")

View File

@@ -1,10 +1,6 @@
import os
from wand.image import Image
from wand.color import Color
import os
canvas_width = 900
canvas_height = 900
def set_canvas_size(width, height):
global canvas_width, canvas_height
@@ -12,6 +8,11 @@ def set_canvas_size(width, height):
canvas_height = int(height)
def resize_image(image_path, output_path, additional_name):
# Normalize the paths to ensure consistency
image_path = os.path.normpath(image_path)
output_path = os.path.normpath(output_path)
with Image(filename=image_path) as img:
img.transform(resize=f'{canvas_width}x{canvas_height}>')
@@ -20,9 +21,14 @@ def resize_image(image_path, output_path, additional_name):
with Image(width=canvas_width, height=canvas_height, background=Color('transparent')) as canvas:
canvas.composite(img, left=x_offset, top=y_offset)
# Create a new filename
new_filename = os.path.splitext(os.path.basename(output_path))[0]
if additional_name:
new_filename += " - " + additional_name.strip()
new_filename += os.path.splitext(output_path)[1]
output_path = os.path.join(os.path.dirname(output_path), new_filename)
canvas.save(filename=output_path)
# Construct the final output path
final_output_path = os.path.join(os.path.dirname(output_path), new_filename)
# Save the image to the final output path
canvas.save(filename=final_output_path)
print(f"Saved to: {final_output_path}")
set_canvas_size(900, 900)