Py2Exe: https://github.com/pyinstaller/pyinstaller
*python-help



Download multiple youtube links to mp4
--------------------------------------

from pytubefix import YouTube
import os
import re
import tkinter as tk
from tkinter import ttk

def sanitize_filename(filename):
    """
    Removes special characters from the filename.
    """
    return re.sub(r'[^\w\-_\. ]', '_', filename)

def log_error(video_url, error_message):
    """
    Appends an error message to log.txt.
    """
    with open("log.txt", "a") as log_file:
        log_file.write(f"Error downloading {video_url}: {error_message}\n")

def download_video(video_url):
    """
    Downloads a single YouTube video by URL.
    """
    try:
        video = YouTube(video_url)
        filename = f"{sanitize_filename(video.title)}.mp4"
        print(f"Downloading: {filename}")
        
        stream = video.streams.filter(file_extension='mp4').first()
        
        # Check if the stream is available
        if not stream:
            print(f"No MP4 streams available for: {video_url}")
            log_error(video_url, "No MP4 streams available.")
            return

        stream.download(filename=filename)
        print(f"Download complete: {filename}")
    except Exception as e:
        print(f"Error downloading video {video_url}: {e}")
        log_error(video_url, str(e))

def download_videos_from_list(video_urls):
    """
    Downloads multiple YouTube videos from a list of URLs.
    """
    for url in video_urls.splitlines():
        url = url.strip()  # Remove any extra whitespace
        if url:  # Ensure the URL is not empty
            download_video(url)

def main():
    root = tk.Tk()
    root.title("YouTube Video Downloader")
    
    url_label = ttk.Label(root, text="YouTube Video URLs (one per line):")
    url_label.pack(pady=10)
    
    url_entry = tk.Text(root, height=10, width=50)  # Use tk.Text for multi-line input
    url_entry.pack(pady=10)
    
    download_button = ttk.Button(root, text="Download Videos", command=lambda: download_videos_from_list(url_entry.get("1.0", tk.END)))
    download_button.pack(pady=10)
    
    root.mainloop()

if __name__ == "__main__":
    main()

__________________________________




Audio File combiner (+ txt with timestamps writer)
--------------------------------------------------


import mutagen
from mutagen.mp3 import MP3
from mutagen.id3 import ID3, TIT2, TPE1
from tkinter import Tk, Label, Entry, Button, Text
from tkinterdnd2 import DND_FILES, TkinterDnD
import os

class MP3Combiner:
    def __init__(self, root):
        self.root = root
        self.root.title("MP3 Combiner")
        
        self.label = Label(root, text="Drag and drop MP3 files here:")
        self.label.pack()

        self.text = Text(root, height=10, width=50)
        self.text.pack()

        self.delay_label = Label(root, text="Enter delay in seconds:")
        self.delay_label.pack()

        self.delay_entry = Entry(root)
        self.delay_entry.pack()

        self.combine_button = Button(root, text="Combine MP3s", command=self.combine_mp3s)
        self.combine_button.pack()

        self.mp3_files = []

        self.root.drop_target_register(DND_FILES)
        self.root.dnd_bind('<<Drop>>', self.on_drop)

    def on_drop(self, event):
        files = self.root.tk.splitlist(event.data)
        for file in files:
            if file.endswith('.mp3'):
                self.mp3_files.append(file)
                self.text.insert('end', f"{file}\n")

    def combine_mp3s(self):
        if not self.mp3_files:
            self.text.insert('end', "Please drop some MP3 files.\n")
            return

        try:
            delay_seconds = float(self.delay_entry.get())
        except ValueError:
            self.text.insert('end', "Please enter a valid number for the delay.\n")
            return

        # Create silent delay file as bytes (no AudioSegment needed)
        delay_data = b'\x00' * int(44100 * 2 * delay_seconds)  # 44100 sample rate, 2 bytes per sample (16-bit)

        # Initialize cumulative time for calculating timestamps
        cumulative_time = 0.0
        txt_output_lines = []

        with open("combined_output.mp3", "wb") as output_file:
            for file in self.mp3_files:
                # Read MP3 metadata for title
                audio = MP3(file, ID3=ID3)
                title = audio.get("TIT2", "Unknown Title")  # Get title, default to "Unknown Title"
                duration = audio.info.length  # Get the duration of the track

                # Write MP3 data to the combined file
                with open(file, "rb") as mp3_file:
                    mp3_data = mp3_file.read()
                    output_file.write(mp3_data)

                # Add current track's timestamp and title to the list
                minutes, seconds = divmod(int(cumulative_time), 60)
                timestamp = f"{minutes:02}:{seconds:02}"
                txt_output_lines.append(f"{timestamp} {title}")

                # Update cumulative time with track duration and delay
                cumulative_time += duration + delay_seconds

                # Append delay to the output file
                output_file.write(delay_data)
            
        # Save metadata to the combined MP3 file
        combined_audio = MP3("combined_output.mp3", ID3=ID3)
        combined_audio["TIT2"] = TIT2(encoding=3, text="Combined MP3")
        combined_audio["TPE1"] = TPE1(encoding=3, text="Various Artists")
        combined_audio.save()

        # Write timestamps and song titles to a text file
        with open("combined_output_timestamps.txt", "w") as txt_file:
            txt_file.write("\n".join(txt_output_lines))

        self.text.insert('end', "Combined audio saved as 'combined_output.mp3'\n")
        self.text.insert('end', "Tracklist with timestamps saved as 'combined_output_timestamps.txt'\n")

if __name__ == "__main__":
    root = TkinterDnD.Tk()
    app = MP3Combiner(root)
    root.mainloop()





____________________________________

MMD file copier (vmd, camera, audio) - drag n drop
--------------------------------------------


import tkinter as tk
from tkinterdnd2 import DND_FILES, TkinterDnD
import os
import shutil

class FileCopyApp:
    def __init__(self, root):
        self.root = root
        self.root.title("File Copy Tool")
        
        # Initialize variables for file paths and base path
        self.base_path = tk.StringVar(value="E:\\Dropbox\\Public\\00_Html\\Examples\\3D_Model_render\\MMD\\SampleWebMMD-master")
        self.camera_path = ""
        self.vmd_path = ""
        self.audio_path = ""
        
        # Create GUI elements
        self.create_gui()
    
    def create_gui(self):
        # Create label and entry for base path
        base_path_label = tk.Label(self.root, text="Base Path:")
        base_path_label.grid(row=0, column=0, padx=10, pady=10, sticky="e")
        
        self.base_path_entry = tk.Entry(self.root, textvariable=self.base_path, width=50)
        self.base_path_entry.grid(row=0, column=1, padx=10, pady=10, sticky="ew")
        
        # Create labels for drop boxes
        tk.Label(self.root, text="Camera").grid(row=1, column=0, padx=10, pady=10)
        tk.Label(self.root, text="VMD").grid(row=1, column=1, padx=10, pady=10)
        tk.Label(self.root, text="Audio").grid(row=1, column=2, padx=10, pady=10)
        
        # Create drop boxes
        self.create_drop_box("camera", row=2, column=0)
        self.create_drop_box("vmd", row=2, column=1)
        self.create_drop_box("audio", row=2, column=2)
        
        # Entry for name
        name_label = tk.Label(self.root, text="Enter a name:")
        name_label.grid(row=3, column=0, columnspan=3, padx=10, pady=10)
        
        self.name_entry = tk.Entry(self.root)
        self.name_entry.grid(row=4, column=0, columnspan=3, padx=10, pady=10, sticky="ew")
        
        # Button to initiate copy process
        copy_button = tk.Button(self.root, text="Copy Files", command=self.copy_files)
        copy_button.grid(row=5, column=0, columnspan=3, padx=10, pady=10, sticky="ew")
        
        # Label for success message
        self.success_label = tk.Label(self.root, text="", fg="green")
        self.success_label.grid(row=6, column=0, columnspan=3, padx=10, pady=10)
        
        # Configure grid layout
        self.root.grid_rowconfigure(2, weight=1)
        self.root.grid_columnconfigure(0, weight=1)
        self.root.grid_columnconfigure(1, weight=1)
        self.root.grid_columnconfigure(2, weight=1)
    
    def create_drop_box(self, target_path, row, column):
        frame = tk.Frame(self.root, borderwidth=2, relief="groove")
        frame.grid(row=row, column=column, padx=10, pady=10, sticky="nsew")
        
        label = tk.Label(frame, text=target_path.capitalize(), anchor="w")
        label.pack(fill="x", padx=10, pady=(10, 5))
        
        drop_box = tk.Listbox(frame, relief="sunken", bd=2, height=5, width=40)
        drop_box.pack(fill="both", padx=10, pady=(0, 10))
        
        # Enable drag and drop handling using tkinterdnd2
        drop_box.drop_target_register(DND_FILES)
        drop_box.dnd_bind('<<Drop>>', lambda event, target=target_path: self.on_drop(event, target, drop_box))
        
    def on_drop(self, event, target_path, drop_box):
        # Handle dropped files
        file_paths = event.data.split()  # Split by spaces to get individual file paths
        if file_paths:
            print(f"Dropped file paths: {file_paths}")  # Debug print for dropped files
            for file_path in file_paths:
                self.on_file_drop(file_path, target_path, drop_box)
    
    def on_file_drop(self, file_path, target_path, drop_box):
        # Handle dropped file path
        print(f"Dropped file path: {file_path}")  # Debug print
        
        # Concatenate parts back into full path if necessary
        if not os.path.isabs(file_path):
            file_path = os.path.join(os.getcwd(), file_path)
        
        if target_path == "camera":
            self.camera_path = file_path
        elif target_path == "vmd":
            self.vmd_path = file_path
        elif target_path == "audio":
            self.audio_path = file_path
        
        # Update drop box display
        file_name = os.path.basename(file_path)
        drop_box.delete(0, tk.END)
        drop_box.insert(tk.END, f"Dropped: {file_name}")
    
    def copy_files(self):
        name = self.name_entry.get().strip()
        
        if name == "":
            self.success_label.config(text="Please enter a name.", fg="red")
            return
        
        self.base_path_value = self.base_path.get().strip()
        
        if not self.base_path_value:
            self.success_label.config(text="Please enter a base path.", fg="red")
            return
        
        if self.camera_path:
            camera_file_name = os.path.basename(self.camera_path)
            _, camera_file_ext = os.path.splitext(camera_file_name)
            new_camera_file_name = f"{name}{camera_file_ext}"
            shutil.copy(self.camera_path, os.path.join(self.base_path_value, "camera", new_camera_file_name))
            print(f"Copied '{camera_file_name}' to {os.path.join(self.base_path_value, 'camera')} as '{new_camera_file_name}'")
        
        if self.vmd_path:
            vmd_file_name = os.path.basename(self.vmd_path)
            _, vmd_file_ext = os.path.splitext(vmd_file_name)
            new_vmd_file_name = f"{name}{vmd_file_ext}"
            shutil.copy(self.vmd_path, os.path.join(self.base_path_value, "vmd", new_vmd_file_name))
            print(f"Copied '{vmd_file_name}' to {os.path.join(self.base_path_value, 'vmd')} as '{new_vmd_file_name}'")
        
        if self.audio_path:
            audio_file_name = os.path.basename(self.audio_path)
            _, audio_file_ext = os.path.splitext(audio_file_name)
            new_audio_file_name = f"{name}{audio_file_ext}"
            shutil.copy(self.audio_path, os.path.join(self.base_path_value, "audio", new_audio_file_name))
            print(f"Copied '{audio_file_name}' to {os.path.join(self.base_path_value, 'audio')} as '{new_audio_file_name}'")
        
        self.success_label.config(text="Files copied successfully.", fg="green")

if __name__ == "__main__":
    root = TkinterDnD.Tk()
    app = FileCopyApp(root)
    root.mainloop()




___________________________________________


Youtube MP3 Playlist Downloader
--------------------------------

from pytube import Playlist
import os
from pydub import AudioSegment
import re
import tkinter as tk
from tkinter import ttk
def sanitize_filename(filename):
    """
    Removes special characters from the filename.
    """
    return re.sub(r'[^\w\-_\. ]', '_', filename)
def download_playlist(playlist_url):
    playlist = Playlist(playlist_url)
    print(f"Downloading {len(playlist)} videos from the playlist.")

    for index, video in enumerate(playlist.videos, start=1):
        filename = f"{index:03d} - {sanitize_filename(video.title)}.mp3"
        print(f"Downloading {filename}")

        try:
            # Download the audio stream as MP3 with 128 kbps bitrate
            audio = video.streams.filter(only_audio=True).first()
            audio.download(filename=filename)

            # Adjust the bitrate to 192 kbps
            audio_segment = AudioSegment.from_file(filename, format="mp3")
            audio_segment.export(filename, format="mp3", bitrate="192k")
        except Exception as e:
            print(f"Error downloading {filename}: {e}")
    print("Playlist download complete.")
def main():
    root = tk.Tk()
    root.title("YouTube Playlist Downloader")
    url_label = ttk.Label(root, text="YouTube Playlist URL:")
    url_label.pack(pady=10)
    url_entry = ttk.Entry(root, width=50)
    url_entry.pack(pady=10)
    download_button = ttk.Button(root, text="Download Playlist", command=lambda: download_playlist(url_entry.get()))
    download_button.pack(pady=10)
    root.mainloop()
if __name__ == "__main__":
    main()

_________________________

Poweramp adb Control
-----------------------------

import subprocess
import tkinter as tk
from pynput import keyboard

def send_adb_command(command):
    ip_address = ip_entry.get()
    port = port_entry.get()
    adb_shell_command = f"adb -s {ip_address}:{port} shell am broadcast 'intent:#Intent;action=com.maxmpz.audioplayer.API_COMMAND;package=com.maxmpz.audioplayer;i.cmd={command};end'"
    subprocess.run(adb_shell_command, shell=True)

def restart():
    ip_address = ip_entry.get()
    port = port_entry.get()
    command = f'adb kill-server && adb start-server && adb connect {ip_address}:{port}'
    subprocess.Popen(['cmd.exe', '/c', 'start', 'cmd.exe', '/k', command])

def handle_key_press(key):
    if key == keyboard.Key.media_play_pause:
        send_adb_command(1)  # Play/Pause
    elif key == keyboard.Key.media_next:
        send_adb_command(4)  # Next Track
    elif key == keyboard.Key.media_previous:
        send_adb_command(5)  # Previous Track

# Create the main window
window = tk.Tk()
window.title("ADB Audio Player Control")

# Create IP address label and text entry
ip_label = tk.Label(window, text="IP Address:")
ip_label.pack()
ip_entry = tk.Entry(window)
ip_entry.insert(0, "192.168.0.101")  # Pre-fill with IP address
ip_entry.pack()

# Create port label and text entry
port_label = tk.Label(window, text="Port:")
port_label.pack()
port_entry = tk.Entry(window)
port_entry.insert(0, "5555")  # Pre-fill with port
port_entry.pack()

# Create previous track button
prev_button = tk.Button(window, text="Previous Track", command=lambda: send_adb_command(5))
prev_button.pack()

# Create play/pause button
play_pause_button = tk.Button(window, text="Play/Pause", command=lambda: send_adb_command(1))
play_pause_button.pack()

# Create next track button
next_button = tk.Button(window, text="Next Track", command=lambda: send_adb_command(4))
next_button.pack()

# Create restart button
restart_button = tk.Button(window, text="Restart", command=restart)
restart_button.pack()

# Bind key presses to button actions
def on_key_press(event):
    key = event.keysym.lower()
    if key == 'xf86audioplay':
        send_adb_command(1)  # Play/Pause
    elif key == 'xf86audionext':
        send_adb_command(4)  # Next Track
    elif key == 'xf86audioprev':
        send_adb_command(5)  # Previous Track

window.bind("<KeyPress>", on_key_press)

# Start the tkinter event loop
window.mainloop()




__________________

Video Converter GUI (ffmpeg)
-------------------------------

import tkinter as tk
from tkinter import filedialog
from tkinter import ttk
import subprocess
from tqdm import tqdm
import configparser
import os
settings_file = "videoconverter_settings.ini"
settings = configparser.ConfigParser()
if os.path.exists(settings_file):
    settings.read(settings_file)
# Create the settings.ini file if it doesn't exist
if not os.path.exists(settings_file):
    settings.add_section("General")
    settings.set("General", "OutputPath", "")
    with open(settings_file, "w") as configfile:
        settings.write(configfile)
def calculate_bitrate(width, height, mode):
    if mode == 'CBR':
        if width <= 640 and height <= 480:
            return 500
        elif width <= 1280 and height <= 720:
            return 1000
        elif width <= 1920 and height <= 1080:
            return 2000
        else:
            return 4000
def open_folder_picker():
    folder_path = filedialog.askdirectory()
    output_path_var.set(folder_path)
    settings.set("General", "OutputPath", folder_path)
    with open(settings_file, "w") as configfile:
        settings.write(configfile)
def convert_videos():
    filetypes = (("Video files", "*.mp4 *.avi"), ("All files", "*.*"))
    filenames = filedialog.askopenfilenames(filetypes=filetypes)
    resolution = resolution_var.get()
    bitrate_mode = bitrate_var.get()
    output_path = output_path_var.get()
    if not output_path:
        output_path = filedialog.askdirectory()
        settings.set("General", "OutputPath", output_path)
        with open(settings_file, "w") as configfile:
            settings.write(configfile)
    for filename in filenames:
        output_filename = os.path.join(output_path, filename.split('/')[-1])
        command = ['ffmpeg', '-i', filename]
        command += ['-vf', f"scale={resolution}"]
        width, height = map(int, resolution.split('x'))
        bitrate = calculate_bitrate(width, height, bitrate_mode)
        command += ['-b:v', f"{bitrate}k"]
        command.append(output_filename)
        with tqdm(total=100, ncols=80, bar_format='{l_bar}{bar}| {n_fmt}/{total_fmt}') as pbar:
            process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            for line in process.stderr:
                line = line.decode().strip()
                if line.startswith('frame='):
                    frame = int(line.split('frame=')[1].split()[0])
                    pbar.update(frame - pbar.n)
                    progress_var.set(pbar.n)
                    progress_text.insert(tk.END, line + '\n')
                    progress_text.see(tk.END)
        print(f"Converted {filename} to {output_filename}")
root = tk.Tk()
root.title("Video Converter")
resolution_frame = tk.Frame(root)
resolution_frame.pack(pady=10)
resolution_label = tk.Label(resolution_frame, text="Resolution:")
resolution_label.pack(side=tk.LEFT)
# Dropdown menu with video resolutions
resolution_var = tk.StringVar(value="640x480")
resolution_dropdown = tk.OptionMenu(resolution_frame, resolution_var, "640x480", "1280x720", "1920x1080")
resolution_dropdown.pack(side=tk.LEFT)
bitrate_frame = tk.Frame(root)
bitrate_frame.pack(pady=10)
bitrate_label = tk.Label(bitrate_frame, text="Bitrate Mode:")
bitrate_label.pack(side=tk.LEFT)
bitrate_var = tk.StringVar(value="CBR")
bitrate_cbr_radio = tk.Radiobutton(bitrate_frame, text="CBR", variable=bitrate_var, value="CBR")
bitrate_cbr_radio.pack(side=tk.LEFT)
bitrate_vbr_radio = tk.Radiobutton(bitrate_frame, text="VBR", variable=bitrate_var, value="VBR")
bitrate_vbr_radio.pack(side=tk.LEFT)
output_path_frame = tk.Frame(root)
output_path_frame.pack(pady=10)
output_path_label = tk.Label(output_path_frame, text="Output Path:")
output_path_label.pack(side=tk.LEFT)
output_path_var = tk.StringVar(value=settings.get("General", "OutputPath", fallback=""))
output_path_entry = tk.Entry(output_path_frame, textvariable=output_path_var, state="readonly")
output_path_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
folder_picker_button = tk.Button(output_path_frame, text="Select Folder", command=open_folder_picker)
folder_picker_button.pack(side=tk.LEFT)
progress_text = tk.Text(root, height=10, width=50)
progress_text.pack(pady=10)
progress_var = tk.DoubleVar(value=0.0)
progress_bar = ttk.Progressbar(root, variable=progress_var, maximum=100)
progress_bar.pack(pady=10)
convert_button = tk.Button(root, text="Convert", command=convert_videos)
convert_button.pack(pady=10)
root.mainloop()




________________________________

Youtube Downloader:
-------------------

import tkinter as tk
from pytube import YouTube
from tkinter import ttk
import os

def download():
    # Get the URL from the text box
    url = url_textbox.get()

    # Create a YouTube object
    yt = YouTube(url)

    # Get the video format from the radio buttons
    if mp4_radio_button.get():
        video_format = "mp4"
        extension = ".mp4"
        res = res_textbox.get()
        stream = yt.streams.filter(res=res).first()
    else:
        video_format = "mp3"
        extension = ".mp3"
        streams = yt.streams.filter(only_audio=True).all()

        # Create a new window to display the available audio streams
        stream_window = tk.Toplevel(root)
        stream_window.title("Select Audio Stream")

        # Display the available audio streams in a listbox
        stream_listbox = tk.Listbox(stream_window)
        for stream in streams:
            stream_listbox.insert(tk.END, f"{stream.abr} ({stream.mime_type})")
        stream_listbox.pack(padx=10, pady=10)

        def select_stream():
            # Get the selected stream
            selected_stream_index = stream_listbox.curselection()[0]
            selected_stream = streams[selected_stream_index]

            # Destroy the stream window
            stream_window.destroy()

            # Set up the progress bar
            progress_bar["maximum"] = selected_stream.filesize
            progress_bar["value"] = 0

            # Set up the title label
            title_label.config(text=f"Downloading: {yt.title}")

            # Download the audio
            filename = yt.title.encode('utf-8') + extension
            selected_stream.download(output_path="downloads", filename=filename)

            # Reset the progress bar and title label
            progress_bar["value"] = 0
            title_label.config(text="")

        # Create a select button to download the selected audio stream
        select_button = tk.Button(stream_window, text="Select", command=select_stream)
        select_button.pack(padx=10, pady=10)

        # Wait for the user to select a stream
        stream_window.wait_window()

    # Download the video or audio
    filename = yt.title + extension
    stream.download(output_path="downloads", filename=filename)

    # Reset the progress bar and title label
    progress_bar["value"] = 0
    title_label.config(text="")

def open_download_folder():
    # Open the download folder
    os.startfile(os.path.abspath("downloads"))

def check_url(*args):
    # Get the URL from the text box
    url = url_textbox.get()

    # Replace https://m.youtube. with https://www.youtube.
    url = url.replace("https://m.youtube.", "https://www.youtube.")

    # Check if the URL is valid
    if not url.startswith("https://www.youtube.com/watch?v="):
        return

    # Create a YouTube object
    yt = YouTube(url)

    # Get the available audio streams
    streams = yt.streams.filter(only_audio=True).all()

    # Create a new window to display the available audio streams
    stream_window = tk.Toplevel(root)
    stream_window.title("Select Audio Stream")

    # Display the available audio streams in a listbox
    stream_listbox = tk.Listbox(stream_window)
    for stream in streams:
        stream_listbox.insert(tk.END, f"{stream.abr} ({stream.mime_type})")
    stream_listbox.pack(padx=10, pady=10)

    def select_stream():
        # Get the selected stream
        selected_stream_index = stream_listbox.curselection()[0]
        selected_stream = streams[selected_stream_index]

        # Destroy the stream window
        stream_window.destroy()

        # Set up the progress bar
        progress_bar["maximum"] = selected_stream.filesize
        progress_bar["value"] = 0

        # Set up the title label
        title_label.config(text=f"Downloading: {yt.title}")

        # Download the audio
        filename = yt.title + ".mp3"
        selected_stream.download(output_path="downloads", filename=filename)

        # Reset the progress bar and title label
        progress_bar["value"] = 0
        title_label.config(text="")

    # Create a select button to download the selected audio stream
    select_button = tk.Button(stream_window, text="Select", command=select_stream)
    select_button.pack(padx=10, pady=10)

    # Wait for the user to select a stream
    stream_window.wait_window()

# Create the GUI
root = tk.Tk()
root.title("YouTube Downloader")

# Create the text box for the video resolution
res_textbox = tk.Entry(root, width=10)
res_textbox.pack()
res_textbox.insert(0, "360p")

# Create the text box for the URL
url_textbox =tk.Entry(root, width=50)
url_textbox.pack(padx=10, pady=10)
url_textbox.bind("<Return>", check_url)

# Create the radio buttons to choose the download format
mp4_radio_button = tk.BooleanVar(value=True)
mp4_radio = ttk.Radiobutton(root, text="MP4", variable=mp4_radio_button, value=True)
mp4_radio.pack()
mp3_radio = ttk.Radiobutton(root, text="MP3", variable=mp4_radio_button, value=False)
mp3_radio.pack()

# Create the download button
download_button = tk.Button(root, text="Download", command=download)
download_button.pack(padx=10, pady=10)

# Create the progress bar
progress_bar = ttk.Progressbar(root, orient=tk.HORIZONTAL, length=300, mode="determinate")
progress_bar.pack(padx=10, pady=10)

# Create the title label
title_label = tk.Label(root, text="")
title_label.pack(padx=10, pady=10)

# Create the button to open the download folder
open_folder_button = tk.Button(root, text="Open Download Folder", command=open_download_folder)
open_folder_button.pack(padx=10, pady=10)

# Start the GUI
root.mainloop()



_________________________________________________________________________


MeteoCtrl Lister (with date search, keyword search and hyperlink support):
------------------------------------------------------------------------

import os
import sys
import tkinter as tk
from datetime import datetime, timezone, timedelta


directory = r'C:\Konfi-Data\Export\json'

german_tz = timezone(timedelta(hours=1), 'CET')

def display_files(file_list):
    for file in file_list:
        file_path = os.path.join(directory, file)
        file_time = os.path.getmtime(file_path)
        dt = datetime.fromtimestamp(file_time, tz=timezone.utc)
        german_time = dt.astimezone(german_tz)
        file_timestamp = f'{file} - {german_time.strftime("%d/%m/%Y %I:%M:%S %p")} ({german_tz.tzname(None)})'
        file_label = tk.Label(root, text=file_timestamp, anchor='w', justify='left', fg='blue', cursor='hand2')
        file_label.pack(fill='x')
        file_label.bind('<Button-1>', lambda event, file_path=file_path: open_file(file_path))

def open_file(file_path):
    try:
        with open(file_path, 'r') as f:
            file_content = f.read()
            text_editor = tk.Toplevel(root)
            text_editor.title(file_path)
            text_editor_text = tk.Text(text_editor)
            text_editor_text.pack(fill='both', expand=True)
            text_editor_text.insert('1.0', file_content)
    except Exception as e:
        tk.messagebox.showerror('Error', str(e))

def get_file_date(file):
    # Get the last modification time of the file
    last_modified_time = os.path.getmtime(os.path.join(directory, file))
    # Convert the last modification time to a datetime object
    last_modified_datetime = datetime.fromtimestamp(last_modified_time, tz=german_tz)
    # Extract the date from the datetime object
    return last_modified_datetime.date()

def search_files(keyword, date_str):
    # Clear the previous search results
    for widget in root.winfo_children():
        if isinstance(widget, tk.Label) or isinstance(widget, tk.Button):
            widget.destroy()
    if keyword or date_str:
        count = 0
        for file in file_list:
            file_date = get_file_date(file)
            if (not keyword or keyword.lower() in file.lower()) and (not date_str or file_date == datetime.strptime(date_str, "%d/%m/%Y").date()):
                count += 1
                file_path = os.path.join(directory, file)
                file_time = os.path.getmtime(file_path)
                dt = datetime.fromtimestamp(file_time, tz=timezone.utc)
                german_time = dt.astimezone(german_tz)
                file_timestamp = f'{file} - {german_time.strftime("%d/%m/%Y %I:%M:%S %p")} ({german_tz.tzname(None)})'
                file_label = tk.Label(root, text=file_timestamp, anchor='w', justify='left', fg='blue', cursor='hand2')
                file_label.pack(fill='x')
                file_label.bind('<Button-1>', lambda event, file_path=file_path: open_file(file_path))
                if keyword:
                    with open(file_path, 'r') as f:
                        for line in f:
                            if keyword.lower() in line.lower():
                                line_label = tk.Label(root, text=line.strip(), anchor='w', justify='left')
                                line_label.pack(fill='x')
        total_count.set(f'Occurrences: {count}')
    else:
        display_files(file_list_sorted)
        total_count.set('Occurrences: 0')

def reload_program():
    python = sys.executable
    args = [os.path.abspath(__file__)]
    os.execl(python, python, *args)

    # Close the current instance of the program
    root.destroy()

    
file_list = os.listdir(directory)
file_info_list = [(file, os.path.getmtime(os.path.join(directory, file))) for file in file_list]
file_info_list_sorted = sorted(file_info_list, key=lambda x: x[1], reverse=True)[:100]
file_list_sorted = [file_info[0] for file_info in file_info_list_sorted]

root = tk.Tk()
root.title('Newest 100 Files')

search_entry = tk.Entry(root)
search_entry.pack()

filter_frame = tk.Frame(root)
filter_frame.pack(side='top', fill='x')

date_label = tk.Label(filter_frame, text='Date (dd/mm/yyyy) [t-todays date:]', font='Helvetica 12', anchor='w', justify='left')
date_label.pack(side='left')

date_entry = tk.Entry(filter_frame)
date_entry.pack(side='left', padx=5)

total_count = tk.StringVar()
total_count.set('Occurrences: 0')
count_label = tk.Label(filter_frame, textvariable=total_count, font='Helvetica 12', anchor='e', justify='right')
count_label.pack(side='right', fill='x', expand=True)

# Create the "RELOAD" button
reload_button = tk.Button(root, text='RELOAD / F5', command=reload_program)
reload_button.pack(side='top', pady=10)
root.bind('<F5>', lambda event: reload_program())

display_files(file_list_sorted)

root.after_id = None

def on_search_entry_change(event):
    # Cancel any existing call to the search function
    if root.after_id is not None:
        root.after_cancel(root.after_id)
    # Schedule a new call to the search function in 1 second
    root.after_id = root.after(1500, search_files, search_entry.get(), date_entry.get())
    # Check if "t" is entered in the date entry
    if event.widget == date_entry and event.char.lower() == "t":
        # Replace "t" with the current date in the format "dd/mm/yyyy"
        today = datetime.now(german_tz).strftime("%d/%m/%Y")
        date_entry.delete(0, tk.END)
        date_entry.insert(0, today)



search_entry.bind('<KeyRelease>', on_search_entry_change)
date_entry.bind('<KeyRelease>', on_search_entry_change)

root.mainloop()


( Source: https://poe.com/Pythonmachine )


=============================
===PythonHelp=================


Set virtual environment (for scot free usage of special programs)
-----------------------------------------------------------------

pip install virtualenv

virtualenv openmmd-env
openmmd-env\Scripts\activate



_____________________________________________________________



Stop Win 11 from auto opening store on cmd "python"
--------------------------------------------------

To prevent Windows from redirecting python to the Microsoft Store, disable the App Execution Alias for Python.

Open Settings:

Press Win + I to open Settings.
Go to Apps > Apps & features.
Manage App Execution Aliases:

Scroll down and click on Manage app execution aliases.
Find the Python entry in the list and toggle it off.

_______________________________________________________

Set python36 as path:
---------------------


setx PATH "%PATH%;C:\Users\User\AppData\Local\Programs\Python\Python36;C:\Users\User\AppData\Local\Programs\Python\Python36\Scripts"


_____________________________________


Start .py without visible cmd (save as *.vbs)
-----------------------------------------------

Set objShell = CreateObject("WScript.Shell")
objShell.Run "C:\adb\PowerampCtrl.py", 0, True
Set objShell = Nothing

________________________________

Start py with minimized cmd:
---------------------------------------------

cmd /c start /min "C:\adb\PowerampCtrl.py"
_________________________

Figure out url from pip installer:
----------------------------------
pip install PyQt5 --log log.txt

________________________________________

Install py for specific version:
--------------------------------

C:\Users\User\AppData\Local\Programs\Python\Python310\Scripts\pip install torch-2.0.1+cu118-cp310-cp310-win_amd64.whl

________________________________________

Install whl:
------------

pip install *.whl

_________________________________________

Python on Android:
------------------

Download: termux.en.download.it/android/downloading

Install the Termux app from the Play Store or F-Droid.
pkg update && pkg upgrade
pkg install python
pkg install python-pip
