Skip to content

Commit bdccbd5

Browse files
committed
Add About window with clickable links and easter egg
Introduces an AboutWindow class displaying program info, clickable GitHub link, and a hidden image easter egg triggered by multiple clicks. Refactors icon setup to use PNG and resource_path for cross-platform compatibility. Updates version to 0.3.0 and adjusts About button to open the new window.
1 parent 751b0ba commit bdccbd5

File tree

1 file changed

+135
-11
lines changed

1 file changed

+135
-11
lines changed

soundscripts_editor.py

Lines changed: 135 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@
88
import re
99
from typing import List, Dict, Any
1010
import sys
11+
import webbrowser
1112

1213
# Константы о программе
13-
ABOUT_TOOL_VERSION = "0.2.9"
14+
ABOUT_TOOL_VERSION = "0.3.0"
1415
ABOUT_TOOL_NAME = f"Soundscripts Editor v{ABOUT_TOOL_VERSION}"
1516
ABOUT_TOOL_DESCRIPTION = "This tool helps to edit soundscripts files used on Source Engine."
1617
ABOUT_TOOL_AUTHOR = "Shitcoded by Ambiabstract (Sergey Shavin)."
1718
ABOUT_TOOL_REQUESTED = "Requested by Aptekarr (Ruslan Pozdnyakov)."
1819
ABOUT_TOOL_LINK = "Github: https://github.com/Ambiabstract/soundscripts_editor"
20+
ABOUT_TOOL_LINK_2 = "https://github.com/Ambiabstract/soundscripts_editor"
1921
ABOUT_TOOL_DISCORD = "Discord: @Ambiabstract"
2022

2123
# Константы технические
@@ -122,15 +124,16 @@
122124
"btn_focuscolor": "#808080", # цвет пунктирной фигни на кнопках
123125
}
124126

127+
# Функции чтобы вытаскивать ресурсы из экзешника
128+
def resource_path(name: str) -> str:
129+
base = getattr(sys, "_MEIPASS", Path(__file__).parent)
130+
return str(Path(base) / name)
131+
125132
# Функция назначения иконок для всех окон
126-
def setup_icons(root):
127-
if sys.platform.startswith("win"):
128-
root.iconbitmap(default=os.path.abspath("soundscripts_editor.ico"))
129-
else:
130-
# для Linux/macOS лучше PNG через iconphoto
131-
from tkinter import PhotoImage
132-
img = PhotoImage(file="soundscripts_editor.png")
133-
root.iconphoto(True, img)
133+
def setup_icons(root: tk.Tk):
134+
img = tk.PhotoImage(file=resource_path("soundscripts_editor.png"))
135+
root.iconphoto(True, img)
136+
root._icon_ref = img
134137

135138
# Особая уличная магия для чёрной шапки окна
136139
if sys.platform == "win32":
@@ -450,7 +453,7 @@ def build_main_ui(self):
450453
self.btn_set_gi.pack(
451454
side=tk.LEFT, padx=buttons_padx
452455
)
453-
self.btn_about = ttk.Button(self.toolbar, text=" About ", command=self.about_window)
456+
self.btn_about = ttk.Button(self.toolbar, text=" About ", command=lambda: AboutWindow(self))
454457
self.btn_about.pack(
455458
side=tk.RIGHT, padx=buttons_padx
456459
)
@@ -1753,8 +1756,8 @@ def on_ok(self):
17531756
def on_cancel(self):
17541757
self.destroy()
17551758

1756-
17571759
# Ебанутые попытки покрасить в тёмный цвет шапку окна редактирования имени ноды
1760+
'''
17581761
def themed_askstring(app, title, prompt, initialvalue, **kwargs):
17591762
kwargs["parent"] = app
17601763
# до вызова: список уже существующих Toplevel
@@ -1775,6 +1778,7 @@ def themed_askstring(app, title, prompt, initialvalue, **kwargs):
17751778
enable_win_dark_titlebar(win, enable=(app.theme == "dark"))
17761779
return result
17771780
'''
1781+
'''
17781782
def themed_askstring(app, title, prompt, **kwargs):
17791783
kwargs["parent"] = app
17801784
# до вызова: список уже существующих Toplevel
@@ -1789,6 +1793,126 @@ def themed_askstring(app, title, prompt, **kwargs):
17891793
return result
17901794
'''
17911795

1796+
# Класс окна с инфой о программе
1797+
class AboutWindow(tk.Toplevel):
1798+
def __init__(self, parent):
1799+
super().__init__(parent)
1800+
self.title("About")
1801+
1802+
# self.minsize(300, 200)
1803+
self.resizable(False, False)
1804+
1805+
# Название программы и скрытый прикол
1806+
self.program_label = tk.Label(
1807+
self,
1808+
text=ABOUT_TOOL_NAME,
1809+
justify="left",
1810+
anchor="w",
1811+
wraplength=380
1812+
)
1813+
self.program_label.pack(padx=10, pady=(10, 0), fill="x")
1814+
self.program_label.bind("<Button-1>", self._on_title_click)
1815+
1816+
# Основной текст
1817+
about_tool_full = ABOUT_TOOL_DESCRIPTION + "\n\n" + ABOUT_TOOL_AUTHOR + "\n" + ABOUT_TOOL_REQUESTED + "\n\n" + ABOUT_TOOL_DISCORD
1818+
text_label = tk.Label(
1819+
self, text=about_tool_full, justify="left", anchor="w", wraplength=380
1820+
)
1821+
text_label.pack(padx=10, pady=10, fill="x")
1822+
1823+
# Кликабельная ссылка
1824+
self._add_link(ABOUT_TOOL_LINK, ABOUT_TOOL_LINK_2)
1825+
# self._add_link(ABOUT_TOOL_DISCORD, "https://discordapp.com/users/237650927484403714")
1826+
1827+
# Счетчик кликов по картинке
1828+
self._click_count = 0
1829+
self.target_clicks_count = 10
1830+
self._secret_shown = False
1831+
1832+
# Картинка
1833+
self.secret_image = tk.PhotoImage(file=resource_path("memas.png"))
1834+
1835+
# Кнопки
1836+
button_frame = tk.Frame(self)
1837+
button_frame.pack(pady=10)
1838+
1839+
ok_button = tk.Button(button_frame, text=" OK ", command=self.on_ok, default="active")
1840+
ok_button.pack(side="left", padx=5)
1841+
1842+
# Enter или Esc = OK
1843+
self.bind("<Return>", lambda event: self.on_ok())
1844+
self.bind("<Escape>", lambda event: self.on_ok())
1845+
1846+
# Сделать окно модальным
1847+
self.transient(parent) # держать поверх parent и не показывать в таскбаре
1848+
self.lift() # поднять
1849+
self.update_idletasks()
1850+
try:
1851+
self.wait_visibility() # на macOS/Wayland помогает дождаться появления
1852+
except Exception:
1853+
pass
1854+
self.focus_force() # или self.focus_set()
1855+
self.grab_set() # модальность
1856+
1857+
# Иногда на Windows полезно кратко сделать topmost, затем снять:
1858+
self.attributes("-topmost", True)
1859+
self.after(10, lambda: self.attributes("-topmost", False))
1860+
1861+
# Центрирование
1862+
self.update_idletasks()
1863+
w = self.winfo_width()
1864+
h = self.winfo_height()
1865+
ws = self.winfo_screenwidth()
1866+
hs = self.winfo_screenheight()
1867+
x = (ws // 2) - (w // 2)
1868+
y = (hs // 2) - (h // 2)
1869+
self.geometry(f"{w}x{h}+{x}+{y}")
1870+
1871+
# Особая уличная магия для чёрной шапки окна
1872+
enable_win_dark_titlebar(self, enable=(parent.theme == "dark"))
1873+
1874+
# Ждать закрытия
1875+
self.wait_window()
1876+
1877+
# Метод создания кликабельных ссылок
1878+
def _add_link(self, text, url):
1879+
link = tk.Label(
1880+
self, text=text, fg="#00FF72", cursor="hand2", font=("Arial", 10, "underline") # #00FFFF
1881+
)
1882+
link.pack(pady=2, anchor="w", padx=10)
1883+
link.bind("<Button-1>", lambda e: webbrowser.open_new(url))
1884+
1885+
# Метод кликов по названию
1886+
def _on_title_click(self, event):
1887+
self._click_count += 1
1888+
if self._click_count >= self.target_clicks_count and not self._secret_shown:
1889+
self._show_secret()
1890+
1891+
# Специальное действие
1892+
def _show_secret(self):
1893+
self._secret_shown = True
1894+
1895+
secret_win = tk.Toplevel(self)
1896+
secret_win.title("lmao title text")
1897+
# secret_win.geometry("250x250")
1898+
secret_win.resizable(False, False)
1899+
1900+
img_label = tk.Label(secret_win, image=self.secret_image)
1901+
img_label.pack(expand=True, pady=20)
1902+
1903+
# Центрирование
1904+
secret_win.update_idletasks()
1905+
w = secret_win.winfo_width()
1906+
h = secret_win.winfo_height()
1907+
ws = secret_win.winfo_screenwidth()
1908+
hs = secret_win.winfo_screenheight()
1909+
x = (ws // 2) - (w // 2)
1910+
y = (hs // 2) - (h // 2)
1911+
secret_win.geometry(f"{w}x{h}+{x}+{y}")
1912+
1913+
def on_ok(self):
1914+
self.destroy()
1915+
17921916
def main():
17931917
app = App()
17941918
setup_icons(app)

0 commit comments

Comments
 (0)