Skip to content

Commit 5cde219

Browse files
authored
Add files via upload
1 parent c11d9d6 commit 5cde219

3 files changed

Lines changed: 661 additions & 0 deletions

File tree

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
import sys
2+
import os
3+
from pathlib import Path
4+
import tkinter as tk
5+
from tkinter import filedialog, messagebox
6+
import ttkbootstrap as tb
7+
import subprocess
8+
9+
# =================== APP CONFIG ===================
10+
APP_NAME = "Mate Desktop Search"
11+
APP_VERSION = "1.0.0"
12+
APP_AUTHOR = "Mate Technologies"
13+
APP_WEBSITE = "https://matetools.gumroad.com"
14+
15+
def resource_path(name):
16+
base = getattr(sys, "_MEIPASS", Path(__file__).parent)
17+
return Path(base) / name
18+
19+
# ================= APP =================
20+
21+
app = tk.Tk()
22+
style_obj = tb.Style(theme="superhero")
23+
24+
app.title(f"{APP_NAME} {APP_VERSION}")
25+
app.geometry("1000x600")
26+
27+
try:
28+
app.iconbitmap(str(resource_path("logo.ico")))
29+
except:
30+
pass
31+
32+
# =================== VARIABLES ===================
33+
34+
indexed_files = []
35+
current_folder = tk.StringVar(master=app, value="")
36+
search_query = tk.StringVar(master=app, value="")
37+
status_text = tk.StringVar(master=app, value="Idle")
38+
39+
# =================== FUNCTIONS ===================
40+
41+
def select_folder():
42+
folder = filedialog.askdirectory()
43+
if folder:
44+
current_folder.set(folder)
45+
index_folder(folder)
46+
47+
def index_folder(folder):
48+
indexed_files.clear()
49+
for root, dirs, files in os.walk(folder):
50+
for f in files:
51+
indexed_files.append(os.path.join(root, f))
52+
53+
status_text.set(f"Indexed {len(indexed_files)} files")
54+
update_results()
55+
56+
def update_results(*args):
57+
query = search_query.get().lower()
58+
59+
results_list.delete(0, tk.END)
60+
61+
if not query:
62+
return
63+
64+
matches = [f for f in indexed_files if query in os.path.basename(f).lower()]
65+
66+
for m in matches[:500]:
67+
results_list.insert(tk.END, m)
68+
69+
status_text.set(f"{len(matches)} result(s)")
70+
71+
def open_selected(event=None):
72+
sel = results_list.curselection()
73+
if not sel:
74+
return
75+
76+
path = results_list.get(sel[0])
77+
78+
try:
79+
if sys.platform.startswith("win"):
80+
os.startfile(path)
81+
elif sys.platform.startswith("darwin"):
82+
subprocess.call(["open", path])
83+
else:
84+
subprocess.call(["xdg-open", path])
85+
except Exception as e:
86+
messagebox.showerror("Error", str(e))
87+
88+
def show_about():
89+
messagebox.showinfo(
90+
f"About {APP_NAME}",
91+
f"{APP_NAME} v{APP_VERSION}\n\n"
92+
"A fast lightweight desktop file search engine.\n\n"
93+
"Features:\n"
94+
"• Folder indexing\n"
95+
"• Instant filename search\n"
96+
"• Double-click to open files\n"
97+
"• Works fully offline\n"
98+
"• Modern ttkbootstrap UI\n\n"
99+
"Use Cases:\n"
100+
"• Find documents quickly\n"
101+
"• Locate media files\n"
102+
"• Search project folders\n\n"
103+
f"{APP_AUTHOR}\n{APP_WEBSITE}"
104+
)
105+
106+
# =================== UI ===================
107+
108+
tb.Label(
109+
app,
110+
text=APP_NAME,
111+
font=("Segoe UI", 18, "bold")
112+
).pack(pady=(10,2))
113+
114+
tb.Label(
115+
app,
116+
text="Instant local file search",
117+
font=("Segoe UI",10,"italic"),
118+
foreground="#9ca3af"
119+
).pack(pady=(0,10))
120+
121+
main_frame = tb.Frame(app)
122+
main_frame.pack(fill="both", expand=True, padx=10, pady=10)
123+
124+
# Left: Results
125+
left = tb.Frame(main_frame)
126+
left.pack(side="left", fill="both", expand=True)
127+
128+
results_list = tk.Listbox(left, bg="#222", fg="white")
129+
results_list.pack(fill="both", expand=True)
130+
131+
results_list.bind("<Double-Button-1>", open_selected)
132+
133+
# Right: Controls
134+
right = tb.Frame(main_frame, width=260)
135+
right.pack(side="right", fill="y", padx=5)
136+
137+
tb.Label(right, text="Indexed Folder:").pack(anchor="w")
138+
tb.Entry(right, textvariable=current_folder).pack(fill="x", pady=3)
139+
140+
tb.Button(
141+
right,
142+
text="Select Folder",
143+
bootstyle="primary",
144+
command=select_folder
145+
).pack(fill="x", pady=5)
146+
147+
tb.Label(right, text="Search:").pack(anchor="w")
148+
149+
search_entry = tb.Entry(right, textvariable=search_query)
150+
search_entry.pack(fill="x", pady=3)
151+
search_entry.bind("<KeyRelease>", update_results)
152+
153+
tb.Button(
154+
right,
155+
text="Open Selected",
156+
bootstyle="success",
157+
command=open_selected
158+
).pack(fill="x", pady=5)
159+
160+
tb.Button(
161+
right,
162+
text="About",
163+
bootstyle="secondary",
164+
command=show_about
165+
).pack(fill="x", pady=5)
166+
167+
tb.Label(right, textvariable=status_text).pack(pady=10)
168+
169+
# =================== RUN ===================
170+
app.mainloop()
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
import sys
2+
import os
3+
import time
4+
from pathlib import Path
5+
import tkinter as tk
6+
from tkinter import filedialog, messagebox
7+
import ttkbootstrap as tb
8+
from PIL import Image, ImageTk
9+
import subprocess
10+
import PyPDF2
11+
12+
# =================== APP CONFIG ===================
13+
APP_NAME = "Mate Desktop Search Pro"
14+
APP_VERSION = "2.0.0"
15+
APP_AUTHOR = "Mate Technologies"
16+
17+
def resource_path(name):
18+
base = getattr(sys, "_MEIPASS", Path(__file__).parent)
19+
return Path(base) / name
20+
21+
# ================= APP =================
22+
23+
app = tk.Tk()
24+
style = tb.Style(theme="superhero")
25+
26+
app.title(f"{APP_NAME} {APP_VERSION}")
27+
app.geometry("1200x650")
28+
29+
# ================= VARIABLES =================
30+
31+
indexed_files = []
32+
recent_files = []
33+
34+
current_folder = tk.StringVar(value="")
35+
search_query = tk.StringVar(value="")
36+
status_text = tk.StringVar(value="Idle")
37+
file_filter = tk.StringVar(value="All")
38+
sort_mode = tk.StringVar(value="Name")
39+
40+
preview_img = None
41+
42+
FILTERS = {
43+
"All": [],
44+
"Images": [".png",".jpg",".jpeg",".gif"],
45+
"Docs": [".txt",".pdf",".docx"],
46+
"Videos": [".mp4",".mov",".avi"]
47+
}
48+
49+
# ================= FUNCTIONS =================
50+
51+
def select_folder():
52+
folder = filedialog.askdirectory()
53+
if folder:
54+
current_folder.set(folder)
55+
index_folder(folder)
56+
57+
def index_folder(folder):
58+
indexed_files.clear()
59+
60+
for root, dirs, files in os.walk(folder):
61+
for f in files:
62+
indexed_files.append(os.path.join(root,f))
63+
64+
status_text.set(f"Indexed {len(indexed_files)} files")
65+
update_results()
66+
67+
def file_matches(path):
68+
ext = Path(path).suffix.lower()
69+
allowed = FILTERS[file_filter.get()]
70+
return not allowed or ext in allowed
71+
72+
def search_content(path, query):
73+
try:
74+
if path.endswith(".txt"):
75+
return query in open(path,errors="ignore").read().lower()
76+
77+
if path.endswith(".pdf"):
78+
reader = PyPDF2.PdfReader(path)
79+
for p in reader.pages[:3]:
80+
if query in p.extract_text().lower():
81+
return True
82+
except:
83+
pass
84+
return False
85+
86+
def update_results(*args):
87+
q = search_query.get().lower()
88+
results.delete(0,tk.END)
89+
90+
matches = []
91+
92+
for f in indexed_files:
93+
if not file_matches(f):
94+
continue
95+
96+
name_match = q in os.path.basename(f).lower()
97+
content_match = q and search_content(f,q)
98+
99+
if not q or name_match or content_match:
100+
matches.append(f)
101+
102+
if sort_mode.get()=="Size":
103+
matches.sort(key=lambda x: os.path.getsize(x))
104+
elif sort_mode.get()=="Date":
105+
matches.sort(key=lambda x: os.path.getmtime(x))
106+
else:
107+
matches.sort()
108+
109+
for m in matches[:500]:
110+
results.insert(tk.END,m)
111+
112+
status_text.set(f"{len(matches)} result(s)")
113+
114+
def open_selected(event=None):
115+
sel = results.curselection()
116+
if not sel: return
117+
path = results.get(sel[0])
118+
119+
recent_files.append(path)
120+
if len(recent_files)>20:
121+
recent_files.pop(0)
122+
123+
try:
124+
if sys.platform.startswith("win"):
125+
os.startfile(path)
126+
elif sys.platform.startswith("darwin"):
127+
subprocess.call(["open", path])
128+
else:
129+
subprocess.call(["xdg-open", path])
130+
except Exception as e:
131+
messagebox.showerror("Error",str(e))
132+
133+
def show_preview(event=None):
134+
global preview_img
135+
sel = results.curselection()
136+
if not sel: return
137+
138+
path = results.get(sel[0])
139+
ext = Path(path).suffix.lower()
140+
141+
preview.delete("all")
142+
143+
try:
144+
if ext in [".png",".jpg",".jpeg",".gif"]:
145+
img = Image.open(path)
146+
img.thumbnail((250,250))
147+
preview_img = ImageTk.PhotoImage(img)
148+
preview.create_image(0,0,anchor="nw",image=preview_img)
149+
150+
elif ext==".txt":
151+
txt = open(path,errors="ignore").read()[:1500]
152+
preview.create_text(5,5,anchor="nw",fill="white",text=txt)
153+
154+
else:
155+
info = f"{Path(path).name}\n\nSize: {os.path.getsize(path)//1024} KB\nModified: {time.ctime(os.path.getmtime(path))}"
156+
preview.create_text(5,5,anchor="nw",fill="white",text=info)
157+
158+
except:
159+
pass
160+
161+
def show_recent():
162+
results.delete(0,tk.END)
163+
for f in reversed(recent_files):
164+
results.insert(tk.END,f)
165+
166+
def show_about():
167+
messagebox.showinfo(
168+
APP_NAME,
169+
f"{APP_NAME} {APP_VERSION}\n\n"
170+
"Advanced desktop search engine.\n\n"
171+
"• Content search TXT/PDF\n"
172+
"• Filters\n"
173+
"• Preview\n"
174+
"• Sorting\n"
175+
"• Recent files\n\n"
176+
"Mate Technologies"
177+
)
178+
179+
# ================= UI =================
180+
181+
tb.Label(app,text=APP_NAME,font=("Segoe UI",18,"bold")).pack(pady=5)
182+
183+
main = tb.Frame(app)
184+
main.pack(fill="both",expand=True,padx=10,pady=10)
185+
186+
# Left
187+
left = tb.Frame(main)
188+
left.pack(side="left",fill="both",expand=True)
189+
190+
results = tk.Listbox(left,bg="#222",fg="white")
191+
results.pack(fill="both",expand=True)
192+
results.bind("<Double-Button-1>",open_selected)
193+
results.bind("<<ListboxSelect>>",show_preview)
194+
195+
# Right
196+
right = tb.Frame(main,width=320)
197+
right.pack(side="right",fill="y",padx=5)
198+
199+
tb.Entry(right,textvariable=current_folder).pack(fill="x")
200+
tb.Button(right,text="Select Folder",bootstyle="primary",command=select_folder).pack(fill="x",pady=3)
201+
202+
tb.Entry(right,textvariable=search_query).pack(fill="x")
203+
search_query.trace_add("write",update_results)
204+
205+
tb.Combobox(right,values=list(FILTERS.keys()),textvariable=file_filter).pack(fill="x",pady=2)
206+
file_filter.trace_add("write",update_results)
207+
208+
tb.Combobox(right,values=["Name","Size","Date"],textvariable=sort_mode).pack(fill="x",pady=2)
209+
sort_mode.trace_add("write",update_results)
210+
211+
tb.Button(right,text="Recent Files",bootstyle="info",command=show_recent).pack(fill="x",pady=3)
212+
tb.Button(right,text="Open",bootstyle="success",command=open_selected).pack(fill="x",pady=3)
213+
tb.Button(right,text="About",bootstyle="secondary",command=show_about).pack(fill="x",pady=3)
214+
215+
preview = tk.Canvas(right,width=250,height=250,bg="#333")
216+
preview.pack(pady=5)
217+
218+
tb.Label(right,textvariable=status_text).pack()
219+
220+
# ================= RUN =================
221+
app.mainloop()

0 commit comments

Comments
 (0)