QuwiftSearch Python GUI

👤 Sharing: AI
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
import os
import threading
import time

class FileSearchApp:
    def __init__(self, master):
        self.master = master
        master.title("QuwiftSearch: The Rapid File Locator")
        master.geometry("800x600")
        master.configure(bg="#f0f0f0")

        # Style Configuration
        style = ttk.Style()
        style.configure('TButton', background='#4CAF50', foreground='black', font=('Arial', 10))
        style.configure('TLabel', background='#f0f0f0', font=('Arial', 10))
        style.configure('TEntry', font=('Arial', 10))
        style.configure('TText', font=('Arial', 10))

        # Variables
        self.search_path = tk.StringVar()
        self.search_query = tk.StringVar()
        self.case_sensitive = tk.BooleanVar()
        self.include_subdirectories = tk.BooleanVar()
        self.running = False  # Flag to control the search thread

        # GUI Elements
        # Directory Selection
        self.path_label = ttk.Label(master, text="Search Directory:")
        self.path_label.grid(row=0, column=0, padx=10, pady=5, sticky=tk.W)

        self.path_entry = ttk.Entry(master, textvariable=self.search_path, width=60)
        self.path_entry.grid(row=0, column=1, padx=10, pady=5, sticky=tk.W)

        self.browse_button = ttk.Button(master, text="Browse", command=self.browse_directory)
        self.browse_button.grid(row=0, column=2, padx=10, pady=5, sticky=tk.W)

        # Search Query
        self.query_label = ttk.Label(master, text="Search Query:")
        self.query_label.grid(row=1, column=0, padx=10, pady=5, sticky=tk.W)

        self.query_entry = ttk.Entry(master, textvariable=self.search_query, width=60)
        self.query_entry.grid(row=1, column=1, padx=10, pady=5, sticky=tk.W)

        # Options
        self.case_check = ttk.Checkbutton(master, text="Case Sensitive", variable=self.case_sensitive)
        self.case_check.grid(row=2, column=0, padx=10, pady=5, sticky=tk.W)

        self.subdirectories_check = ttk.Checkbutton(master, text="Include Subdirectories", variable=self.include_subdirectories)
        self.subdirectories_check.grid(row=2, column=1, padx=10, pady=5, sticky=tk.W)

        # Buttons
        self.search_button = ttk.Button(master, text="Start Search", command=self.start_search)
        self.search_button.grid(row=3, column=0, columnspan=3, pady=10)

        self.stop_button = ttk.Button(master, text="Stop Search", command=self.stop_search, state=tk.DISABLED)
        self.stop_button.grid(row=4, column=0, columnspan=3, pady=10)

        self.details_button = ttk.Button(master, text="Details", command=self.show_details)
        self.details_button.grid(row=5, column=0, columnspan=3, pady=10)

        # Results Display
        self.results_label = ttk.Label(master, text="Search Results:")
        self.results_label.grid(row=6, column=0, padx=10, pady=5, sticky=tk.W)

        self.results_text = tk.Text(master, wrap=tk.WORD, height=15, width=80)
        self.results_text.grid(row=7, column=0, columnspan=3, padx=10, pady=5, sticky=tk.W)
        self.results_text.config(state=tk.DISABLED)

        # Scrollbar
        self.scrollbar = ttk.Scrollbar(master, command=self.results_text.yview)
        self.scrollbar.grid(row=7, column=3, sticky='nsew')
        self.results_text['yscrollcommand'] = self.scrollbar.set

        # Status Bar
        self.status_label = ttk.Label(master, text="Ready", anchor=tk.W)
        self.status_label.grid(row=8, column=0, columnspan=3, sticky=tk.EW, padx=10, pady=5)

    def browse_directory(self):
        directory = filedialog.askdirectory()
        if directory:
            self.search_path.set(directory)

    def start_search(self):
        if not self.running:
            self.running = True
            self.results_text.config(state=tk.NORMAL)
            self.results_text.delete("1.0", tk.END)
            self.results_text.config(state=tk.DISABLED)
            self.search_button.config(state=tk.DISABLED)
            self.stop_button.config(state=tk.NORMAL)
            self.status_label.config(text="Searching...")
            threading.Thread(target=self.perform_search).start()

    def stop_search(self):
        self.running = False

    def perform_search(self):
        search_path = self.search_path.get()
        search_query = self.search_query.get()
        case_sensitive = self.case_sensitive.get()
        include_subdirectories = self.include_subdirectories.get()

        if not search_path:
            self.update_status("Error: Please select a directory.")
            self.enable_buttons()
            return
        if not search_query:
             self.update_status("Error: Please enter a search query.")
             self.enable_buttons()
             return

        try:
            if include_subdirectories:
                for root, _, files in os.walk(search_path):
                    if not self.running:  # Check if the search should be stopped
                        break
                    for file in files:
                        if not self.running:
                            break
                        file_path = os.path.join(root, file)
                        if self.search_file(file_path, search_query, case_sensitive):
                            self.update_results(file_path)
            else:
                for file in os.listdir(search_path):
                    if not self.running:
                        break
                    file_path = os.path.join(search_path, file)
                    if os.path.isfile(file_path):
                        if self.search_file(file_path, search_query, case_sensitive):
                            self.update_results(file_path)
        except Exception as e:
            self.update_status(f"Error: {str(e)}")

        self.enable_buttons()
        self.update_status("Search Complete.")
        self.running = False

    def search_file(self, file_path, search_query, case_sensitive):
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
                if case_sensitive:
                    return search_query in content
                else:
                    return search_query.lower() in content.lower()
        except UnicodeDecodeError:
            return False # Ignore binary files
        except Exception as e:
            self.update_status(f"Error reading {file_path}: {str(e)}")
            return False

    def update_results(self, result):
        self.results_text.config(state=tk.NORMAL)
        self.results_text.insert(tk.END, result + "\n")
        self.results_text.config(state=tk.DISABLED)

    def update_status(self, message):
        self.status_label.config(text=message)

    def enable_buttons(self):
        self.search_button.config(state=tk.NORMAL)
        self.stop_button.config(state=tk.DISABLED)

    def show_details(self):
        details_window = tk.Toplevel(self.master)
        details_window.title("QuwiftSearch Details")
        details_window.geometry("600x400")

        details_text = tk.Text(details_window, wrap=tk.WORD)
        details_text.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        details_text.insert(tk.END, "QuwiftSearch is a powerful and efficient file search tool designed to quickly locate files containing specific text within a given directory. It offers several features, including:")
        details_text.insert(tk.END, "\n\n- Directory Selection: Allows users to specify the directory to search.")
        details_text.insert(tk.END, "\n- Search Query: Enables users to enter the text to search for.")
        details_text.insert(tk.END, "\n- Case Sensitivity: Offers the option to perform case-sensitive or case-insensitive searches.")
        details_text.insert(tk.END, "\n- Subdirectory Inclusion: Allows users to include or exclude subdirectories in the search.")
        details_text.insert(tk.END, "\n- Real-time Results: Displays search results as they are found.")
        details_text.insert(tk.END, "\n- Stop Functionality: Provides a button to stop the search at any time.")
        details_text.insert(tk.END, "\n- Status Updates: Informs the user of the current search status.")
        details_text.insert(tk.END, "\n\nQuwiftSearch is ideal for developers, writers, researchers, and anyone who needs to quickly find specific information within a large number of files. It prioritizes speed, accuracy, and user-friendliness.")
        details_text.config(state=tk.DISABLED)

root = tk.Tk()
app = FileSearchApp(root)
root.mainloop()
👁️ Viewed: 6

Comments