Compare commits
8 Commits
2.06.0725
...
04-06-2025
Author | SHA1 | Date | |
---|---|---|---|
7b8ec10e6c | |||
47aa3ac749 | |||
ddae246d46 | |||
c8d439d428 | |||
2463d63c12 | |||
70d973e9d7 | |||
54b62fd5d5 | |||
794dda346a |
36
Changelog
@ -6,9 +6,43 @@ My standard System: Linux Mint 22 Cinnamon
|
|||||||
- os import in common_tools.py replaced by other methods
|
- os import in common_tools.py replaced by other methods
|
||||||
- If Wire-Py already runs, prevent further start
|
- If Wire-Py already runs, prevent further start
|
||||||
- for loops with lists replaced by List Comprehensions
|
- for loops with lists replaced by List Comprehensions
|
||||||
- Tunnel in tk.canvas for modern look
|
|
||||||
- Replace Download Button with Lx Tools installer
|
- Replace Download Button with Lx Tools installer
|
||||||
|
|
||||||
|
### Added
|
||||||
|
02-07-2025
|
||||||
|
|
||||||
|
- Complete code for faulty f" string configuration dur addicted and fixed
|
||||||
|
|
||||||
|
- updater replace Downloadbutton with Lx Tools installer
|
||||||
|
|
||||||
|
- remove logviewer icon
|
||||||
|
|
||||||
|
- add settings.png icon for update button
|
||||||
|
|
||||||
|
|
||||||
|
### Added
|
||||||
|
27-06-2025
|
||||||
|
|
||||||
|
- Header added for more modern desing
|
||||||
|
|
||||||
|
- Sizes adjust the frames and labels improve
|
||||||
|
|
||||||
|
- More modern desing for listbox, Address, Dns and Endpoint
|
||||||
|
|
||||||
|
- ui works now better with rename button
|
||||||
|
|
||||||
|
- add Image class for manage Images
|
||||||
|
|
||||||
|
### Added
|
||||||
|
23-06-2025
|
||||||
|
|
||||||
|
- all msg_window with MassageDialog replaced
|
||||||
|
|
||||||
|
### Added
|
||||||
|
14-06-2025
|
||||||
|
|
||||||
|
- replace msg_window with MassageDialog
|
||||||
|
- vpn stop icon corrected
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
07-06-2025
|
07-06-2025
|
||||||
|
BIN
lx-icons/128/Lunix_Tools.png
Normal file
After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.5 KiB |
BIN
lx-icons/128/question_mark.png
Normal file
After Width: | Height: | Size: 7.0 KiB |
BIN
lx-icons/128/warning.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 10 KiB |
BIN
lx-icons/16/settings.png
Normal file
After Width: | Height: | Size: 575 B |
BIN
lx-icons/16/wg_vpn.png
Normal file
After Width: | Height: | Size: 846 B |
BIN
lx-icons/256/Lunix_Tools.png
Normal file
After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 9.8 KiB |
BIN
lx-icons/256/question_mark.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
lx-icons/256/warning.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 20 KiB |
BIN
lx-icons/32/Lunix_Tools.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.2 KiB |
BIN
lx-icons/32/question_mark.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
lx-icons/32/warning.png
Normal file
After Width: | Height: | Size: 838 B |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 1.9 KiB |
BIN
lx-icons/32/wg_vpn.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
lx-icons/48/Lunix_Tools.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.9 KiB |
BIN
lx-icons/48/question_mark.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
lx-icons/48/warning.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 3.1 KiB |
BIN
lx-icons/64/Lunix_Tools.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.5 KiB |
BIN
lx-icons/64/question_mark.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
lx-icons/64/warning.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 4.5 KiB |
@ -6,25 +6,23 @@ import pwd
|
|||||||
import shutil
|
import shutil
|
||||||
from subprocess import CompletedProcess, run
|
from subprocess import CompletedProcess, run
|
||||||
from shared_libs.wp_app_config import AppConfig
|
from shared_libs.wp_app_config import AppConfig
|
||||||
from shared_libs.common_tools import LxTools
|
from shared_libs.message import MessageDialog
|
||||||
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("--user", required=True, help="Username of the target file system")
|
parser.add_argument("--user", required=True, help="Username of the target file system")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
_ = AppConfig.setup_translations()
|
||||||
try:
|
try:
|
||||||
# Retrieve UID and GID
|
# Retrieve UID and GID
|
||||||
user_info = pwd.getpwnam(args.user)
|
user_info = pwd.getpwnam(args.user)
|
||||||
uid = user_info.pw_uid # User ID (e.g., 1000)
|
uid = user_info.pw_uid # User ID (e.g., 1000)
|
||||||
gid = user_info.pw_gid # Group ID (e.g., 1000)
|
gid = user_info.pw_gid # Group ID (e.g., 1000)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
LxTools.msg_window(
|
MessageDialog(
|
||||||
AppConfig.IMAGE_PATHS["icon_error"],
|
"error", _(f"User '{args.user}' not found."), title="Error decrypt"
|
||||||
AppConfig.IMAGE_PATHS["icon_error"],
|
).show()
|
||||||
"Error decrypt",
|
|
||||||
f"User '{args.user}' not found.",
|
|
||||||
exc_info=True,
|
|
||||||
)
|
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
crypted_tunnel: Path = Path(f"/home/{args.user}/.config/wire_py")
|
crypted_tunnel: Path = Path(f"/home/{args.user}/.config/wire_py")
|
||||||
@ -32,9 +30,9 @@ crypted_tunnel: Path = Path(f"/home/{args.user}/.config/wire_py")
|
|||||||
if len([str(file) for file in crypted_tunnel.glob("*.dat")]) == 0:
|
if len([str(file) for file in crypted_tunnel.glob("*.dat")]) == 0:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
crypted__tunnel = [str(file) for file in crypted_tunnel.glob("*.dat")]
|
crypted_tunnel = [str(file) for file in crypted_tunnel.glob("*.dat")]
|
||||||
|
|
||||||
for tunnel_path in crypted__tunnel:
|
for tunnel_path in crypted_tunnel:
|
||||||
|
|
||||||
base_name = Path(tunnel_path).stem
|
base_name = Path(tunnel_path).stem
|
||||||
|
|
||||||
@ -52,15 +50,16 @@ else:
|
|||||||
],
|
],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
check=False,
|
check=True,
|
||||||
)
|
)
|
||||||
shutil.chown(f"{AppConfig.TEMP_DIR}/{base_name}.conf", uid, gid)
|
shutil.chown(f"{AppConfig.TEMP_DIR}/{base_name}.conf", uid, gid)
|
||||||
|
|
||||||
# Output from Openssl Error
|
# Output from Openssl Error
|
||||||
if process.stderr:
|
if process.stderr:
|
||||||
LxTools.msg_window(
|
MessageDialog(
|
||||||
AppConfig.IMAGE_PATHS["icon_error"],
|
"error",
|
||||||
AppConfig.IMAGE_PATHS["icon_error"],
|
_(
|
||||||
"Error decrypt",
|
f"{process.stderr} Error by [{tunnel_path}] Code: {process.returncode}"
|
||||||
f"{process.stderr} Error by [{tunnel_path}] Code: {process.returncode}",
|
),
|
||||||
)
|
title="Error decrypt",
|
||||||
|
).show()
|
||||||
|
32
tunnel.py
@ -9,6 +9,7 @@ from subprocess import run, CompletedProcess
|
|||||||
import secrets
|
import secrets
|
||||||
from shared_libs.wp_app_config import AppConfig, Msg
|
from shared_libs.wp_app_config import AppConfig, Msg
|
||||||
from shared_libs.common_tools import LxTools, CryptoUtil
|
from shared_libs.common_tools import LxTools, CryptoUtil
|
||||||
|
from shared_libs.message import MessageDialog
|
||||||
|
|
||||||
# Translate
|
# Translate
|
||||||
_ = AppConfig.setup_translations()
|
_ = AppConfig.setup_translations()
|
||||||
@ -172,12 +173,8 @@ class Tunnel:
|
|||||||
CryptoUtil.decrypt(getpass.getuser())
|
CryptoUtil.decrypt(getpass.getuser())
|
||||||
if len([file.name for file in AppConfig.TEMP_DIR.glob("*.conf")]) == 0:
|
if len([file.name for file in AppConfig.TEMP_DIR.glob("*.conf")]) == 0:
|
||||||
|
|
||||||
LxTools.msg_window(
|
MessageDialog("info", Msg.STR["tl_first"], title=Msg.STR["sel_tl"])
|
||||||
AppConfig.IMAGE_PATHS["icon_info"],
|
|
||||||
AppConfig.IMAGE_PATHS["icon_msg"],
|
|
||||||
Msg.STR["sel_tl"],
|
|
||||||
Msg.STR["tl_first"],
|
|
||||||
)
|
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
wg_tar: str = f"{AppConfig.BASE_DIR}/{now_datetime}"
|
wg_tar: str = f"{AppConfig.BASE_DIR}/{now_datetime}"
|
||||||
@ -186,22 +183,20 @@ class Tunnel:
|
|||||||
with zipfile.ZipFile(f"{wg_tar}.zip", "r") as zf:
|
with zipfile.ZipFile(f"{wg_tar}.zip", "r") as zf:
|
||||||
if zf.namelist():
|
if zf.namelist():
|
||||||
|
|
||||||
LxTools.msg_window(
|
MessageDialog(
|
||||||
AppConfig.IMAGE_PATHS["icon_info"],
|
"info",
|
||||||
AppConfig.IMAGE_PATHS["icon_vpn"],
|
|
||||||
Msg.STR["exp_succ"],
|
|
||||||
Msg.STR["exp_in_home"],
|
Msg.STR["exp_in_home"],
|
||||||
|
title=Msg.STR["exp_succ"],
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logging.error(
|
logging.error(
|
||||||
"There was a mistake at creating the Zip file. File is empty."
|
"There was a mistake at creating the Zip file. File is empty."
|
||||||
)
|
)
|
||||||
LxTools.msg_window(
|
MessageDialog(
|
||||||
AppConfig.IMAGE_PATHS["icon_error"],
|
"error", Msg.STR["exp_zip"], title=Msg.STR["exp_err"]
|
||||||
AppConfig.IMAGE_PATHS["icon_msg"],
|
|
||||||
Msg.STR["exp_err"],
|
|
||||||
Msg.STR["exp_zip"],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
@ -217,12 +212,7 @@ class Tunnel:
|
|||||||
pass
|
pass
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Export failed: {str(e)}")
|
logging.error(f"Export failed: {str(e)}")
|
||||||
LxTools.msg_window(
|
MessageDialog("error", Msg.STR["exp_try"], title=Msg.STR["exp_err"])
|
||||||
AppConfig.IMAGE_PATHS["icon_error"],
|
|
||||||
AppConfig.IMAGE_PATHS["icon_msg"],
|
|
||||||
Msg.STR["exp_err"],
|
|
||||||
Msg.STR["exp_try"],
|
|
||||||
)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
524
wirepy.py
@ -6,13 +6,16 @@ import logging
|
|||||||
import getpass
|
import getpass
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
import webbrowser
|
import webbrowser
|
||||||
|
from functools import partial
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from subprocess import CompletedProcess, run
|
from subprocess import CompletedProcess, run
|
||||||
from tkinter import TclError, filedialog, ttk
|
from tkinter import TclError, filedialog, ttk
|
||||||
from tunnel import Tunnel
|
from tunnel import Tunnel
|
||||||
|
from shared_libs.message import MessageDialog
|
||||||
from shared_libs.gitea import GiteaUpdate
|
from shared_libs.gitea import GiteaUpdate
|
||||||
from shared_libs.common_tools import (
|
from shared_libs.common_tools import (
|
||||||
LxTools,
|
LxTools,
|
||||||
@ -23,7 +26,7 @@ from shared_libs.common_tools import (
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
)
|
)
|
||||||
|
|
||||||
from shared_libs.wp_app_config import AppConfig, Msg
|
from shared_libs.wp_app_config import AppConfig, Image, Msg
|
||||||
|
|
||||||
|
|
||||||
class Wirepy(tk.Tk):
|
class Wirepy(tk.Tk):
|
||||||
@ -38,6 +41,7 @@ class Wirepy(tk.Tk):
|
|||||||
self.withdraw()
|
self.withdraw()
|
||||||
|
|
||||||
self.my_tool_tip = None
|
self.my_tool_tip = None
|
||||||
|
|
||||||
self.x_width = AppConfig.UI_CONFIG["window_size"][0]
|
self.x_width = AppConfig.UI_CONFIG["window_size"][0]
|
||||||
self.y_height = AppConfig.UI_CONFIG["window_size"][1]
|
self.y_height = AppConfig.UI_CONFIG["window_size"][1]
|
||||||
|
|
||||||
@ -47,23 +51,29 @@ class Wirepy(tk.Tk):
|
|||||||
AppConfig.UI_CONFIG["resizable_window"][0],
|
AppConfig.UI_CONFIG["resizable_window"][0],
|
||||||
AppConfig.UI_CONFIG["resizable_window"][1],
|
AppConfig.UI_CONFIG["resizable_window"][1],
|
||||||
)
|
)
|
||||||
|
self.minsize(
|
||||||
|
AppConfig.UI_CONFIG["window_size"][0],
|
||||||
|
AppConfig.UI_CONFIG["window_size"][1],
|
||||||
|
)
|
||||||
self.title(AppConfig.UI_CONFIG["window_title"])
|
self.title(AppConfig.UI_CONFIG["window_title"])
|
||||||
|
self.image_manager = Image()
|
||||||
self.columnconfigure(0, weight=1)
|
|
||||||
self.rowconfigure(0, weight=1)
|
|
||||||
self.tk.call("source", f"{AppConfig.SYSTEM_PATHS['tcl_path']}/water.tcl")
|
self.tk.call("source", f"{AppConfig.SYSTEM_PATHS['tcl_path']}/water.tcl")
|
||||||
ConfigManager.init(AppConfig.SETTINGS_FILE)
|
ConfigManager.init(AppConfig.SETTINGS_FILE)
|
||||||
theme = ConfigManager.get("theme")
|
theme = ConfigManager.get("theme")
|
||||||
ThemeManager.change_theme(self, theme)
|
ThemeManager.change_theme(self, theme)
|
||||||
|
|
||||||
# Load the image file from the disk
|
# Try to set icon
|
||||||
self.wg_icon = tk.PhotoImage(file=AppConfig.IMAGE_PATHS["icon_vpn"])
|
try:
|
||||||
|
icon = self.image_manager.load_image("icon_vpn")
|
||||||
# Set it as the window icon
|
if icon:
|
||||||
self.iconphoto(True, self.wg_icon)
|
self.iconphoto(True, icon)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
# Add the widgets
|
# Add the widgets
|
||||||
FrameWidgets(self).grid()
|
FrameWidgets(self).grid()
|
||||||
|
self.columnconfigure(0, weight=1)
|
||||||
|
self.rowconfigure(0, weight=1)
|
||||||
|
|
||||||
# Center the window on the primary monitor
|
# Center the window on the primary monitor
|
||||||
LxTools.center_window_cross_platform(self, self.x_width, self.y_height)
|
LxTools.center_window_cross_platform(self, self.x_width, self.y_height)
|
||||||
@ -86,13 +96,14 @@ class FrameWidgets(ttk.Frame):
|
|||||||
self.dns = None
|
self.dns = None
|
||||||
self.address = None
|
self.address = None
|
||||||
self.auto_con = None
|
self.auto_con = None
|
||||||
self.style = ttk.Style()
|
self.image_manager = Image()
|
||||||
self.wg_vpn_start = tk.PhotoImage(file=AppConfig.IMAGE_PATHS["icon_start"])
|
self.columnconfigure(0, weight=1)
|
||||||
self.wg_vpn_stop = tk.PhotoImage(file=AppConfig.IMAGE_PATHS["icon_stop"])
|
self.rowconfigure(0, weight=1)
|
||||||
self.imp_pic = tk.PhotoImage(file=AppConfig.IMAGE_PATHS["icon_import"])
|
self.columnconfigure(1, weight=1)
|
||||||
self.tr_pic = tk.PhotoImage(file=AppConfig.IMAGE_PATHS["icon_trash"])
|
self.rowconfigure(1, weight=1)
|
||||||
self.exp_pic = tk.PhotoImage(file=AppConfig.IMAGE_PATHS["icon_export"])
|
self.columnconfigure(2, weight=18)
|
||||||
self.warning_pic = tk.PhotoImage(file=AppConfig.IMAGE_PATHS["icon_error"])
|
self.rowconfigure(2, weight=1)
|
||||||
|
self.rowconfigure(3, weight=1)
|
||||||
|
|
||||||
# StringVar-Variables initialization
|
# StringVar-Variables initialization
|
||||||
self.tooltip_state = tk.BooleanVar()
|
self.tooltip_state = tk.BooleanVar()
|
||||||
@ -121,20 +132,10 @@ class FrameWidgets(ttk.Frame):
|
|||||||
|
|
||||||
# Frame for Menu
|
# Frame for Menu
|
||||||
self.menu_frame = ttk.Frame(self)
|
self.menu_frame = ttk.Frame(self)
|
||||||
self.menu_frame.configure(relief="flat")
|
self.menu_frame.grid(column=0, columnspan=3, row=1, sticky="we")
|
||||||
self.menu_frame.grid(column=0, row=0, columnspan=4, sticky="w")
|
|
||||||
|
|
||||||
# App Menu
|
|
||||||
self.version_lb = ttk.Label(self.menu_frame, text=AppConfig.VERSION)
|
|
||||||
self.version_lb.config(font=("Ubuntu", 11), foreground="#00c4ff")
|
|
||||||
self.version_lb.grid(column=0, row=0, rowspan=4, padx=10)
|
|
||||||
|
|
||||||
Tooltip(
|
|
||||||
self.version_lb, f"Version: {AppConfig.VERSION[2:]}", self.tooltip_state
|
|
||||||
)
|
|
||||||
|
|
||||||
self.options_btn = ttk.Menubutton(self.menu_frame, text=_("Options"))
|
self.options_btn = ttk.Menubutton(self.menu_frame, text=_("Options"))
|
||||||
self.options_btn.grid(column=1, columnspan=1, row=0)
|
self.options_btn.grid(column=0, row=0)
|
||||||
|
|
||||||
Tooltip(self.options_btn, Msg.TTIP["settings"], self.tooltip_state)
|
Tooltip(self.options_btn, Msg.TTIP["settings"], self.tooltip_state)
|
||||||
|
|
||||||
@ -146,9 +147,8 @@ class FrameWidgets(ttk.Frame):
|
|||||||
command=lambda: self.update_setting(self.set_update.get()),
|
command=lambda: self.update_setting(self.set_update.get()),
|
||||||
variable=self.set_update,
|
variable=self.set_update,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.updates_lb = ttk.Label(self.menu_frame, textvariable=self.update_label)
|
self.updates_lb = ttk.Label(self.menu_frame, textvariable=self.update_label)
|
||||||
self.updates_lb.grid(column=4, columnspan=3, row=0, padx=10)
|
self.updates_lb.grid(column=2, row=0)
|
||||||
self.updates_lb.grid_remove()
|
self.updates_lb.grid_remove()
|
||||||
self.update_label.trace_add("write", self.update_label_display)
|
self.update_label.trace_add("write", self.update_label_display)
|
||||||
self.update_foreground.trace_add("write", self.update_label_display)
|
self.update_foreground.trace_add("write", self.update_label_display)
|
||||||
@ -176,69 +176,148 @@ class FrameWidgets(ttk.Frame):
|
|||||||
self.about_btn = ttk.Button(
|
self.about_btn = ttk.Button(
|
||||||
self.menu_frame, text=_("About"), style="Toolbutton", command=self.about
|
self.menu_frame, text=_("About"), style="Toolbutton", command=self.about
|
||||||
)
|
)
|
||||||
self.about_btn.grid(column=2, columnspan=2, row=0)
|
self.about_btn.grid(column=1, row=0)
|
||||||
self.readme = tk.Menu(self)
|
|
||||||
|
|
||||||
self.a = Tunnel.get_active()
|
self.a = Tunnel.get_active()
|
||||||
|
|
||||||
# Label Frame 1
|
# Header Frame
|
||||||
self.lb_frame_btn_lbox = ttk.Frame(self)
|
# Festlegen der Farbe
|
||||||
self.lb_frame_btn_lbox.configure(relief="flat")
|
self.header_frame = tk.Frame(self, bg="#2c3e50")
|
||||||
self.lb_frame_btn_lbox.grid(column=0, rowspan=3, row=1)
|
self.wg_icon_header_frame = tk.Frame(self.header_frame, bg="#2c3e50")
|
||||||
|
self.header_label = tk.Label(
|
||||||
# Label Frame 2
|
self.header_frame,
|
||||||
self.lb_frame = ttk.Frame(self)
|
text=_("Lx Tools Wire-Py"),
|
||||||
self.lb_frame.configure(relief="solid")
|
font=("Helvetica", 12, "bold"),
|
||||||
self.lb_frame.grid(column=2, row=2, sticky="snew", padx=20, pady=5)
|
fg="#ffffff",
|
||||||
|
bg="#2c3e50",
|
||||||
# Label Frame 3
|
|
||||||
self.lb_frame2 = ttk.Frame(self)
|
|
||||||
self.lb_frame2.configure(relief="solid")
|
|
||||||
self.lb_frame2.grid(column=2, row=3, sticky="snew", padx=20, pady=5)
|
|
||||||
|
|
||||||
# Bottom Frame 4
|
|
||||||
self.lb_frame3 = ttk.Frame(self)
|
|
||||||
self.lb_frame3.configure(relief="flat")
|
|
||||||
self.lb_frame3.grid(
|
|
||||||
column=0, row=5, columnspan=4, sticky="snew", padx=2, pady=2
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Bottom Frame 5
|
self.version_label = tk.Label(
|
||||||
self.lb_frame4 = ttk.Frame(self)
|
self.header_frame,
|
||||||
self.lb_frame4.configure(relief="flat")
|
text=f"{AppConfig.VERSION} • {Msg.STR['header_left_bottom']}",
|
||||||
self.lb_frame4.grid(column=2, row=5, columnspan=3, sticky="e", padx=15)
|
font=("Helvetica", 9),
|
||||||
|
fg="#bdc3c7",
|
||||||
|
bg="#2c3e50",
|
||||||
|
)
|
||||||
|
self.info_label = tk.Label(
|
||||||
|
self.header_frame,
|
||||||
|
text=Msg.STR["header_right_top"],
|
||||||
|
font=("Helvetica", 10),
|
||||||
|
fg="#ecf0f1",
|
||||||
|
bg="#2c3e50",
|
||||||
|
)
|
||||||
|
self.header_frame.grid(column=0, columnspan=3, row=0, sticky="nsew")
|
||||||
|
self.wg_icon_header_frame.grid(column=0, row=0, rowspan=2, sticky="w")
|
||||||
|
|
||||||
|
self.wg_icon_header_label = tk.Label(
|
||||||
|
self.wg_icon_header_frame,
|
||||||
|
image=self.image_manager.load_image("icon_header"),
|
||||||
|
bg="#2c3e50",
|
||||||
|
)
|
||||||
|
self.wg_icon_header_label.grid(column=0, row=0, sticky="e", ipadx=10)
|
||||||
|
|
||||||
|
self.header_label.grid(
|
||||||
|
column=1,
|
||||||
|
row=0,
|
||||||
|
sticky="w",
|
||||||
|
padx=(5, 20),
|
||||||
|
pady=(10, 0),
|
||||||
|
ipady=4,
|
||||||
|
)
|
||||||
|
self.version_label.grid(column=1, row=1, sticky="w", padx=(5, 20), pady=(0, 10))
|
||||||
|
self.info_label.grid(column=2, row=0, sticky="ne", padx=(10, 10), pady=(10, 0))
|
||||||
|
self.header_frame.columnconfigure(1, weight=1, pad=2)
|
||||||
|
self.header_frame.rowconfigure(0, weight=1)
|
||||||
|
|
||||||
|
# Frame for Control Buttons (Start, Stop, Import, Trash, Export)
|
||||||
|
self.control_buttons_frame = ttk.Frame(self)
|
||||||
|
self.control_buttons_frame.grid(column=0, row=2, sticky="w", padx=(15, 0))
|
||||||
|
self.control_buttons_frame.columnconfigure(0, weight=1)
|
||||||
|
self.control_buttons_frame.rowconfigure(2, weight=1)
|
||||||
|
|
||||||
|
# Frame for Listbox and Scrollbar
|
||||||
|
self.list_container_frame = ttk.Frame(self)
|
||||||
|
self.list_container_frame.grid(column=1, row=2, sticky="nsew", pady=3)
|
||||||
|
self.list_container_frame.columnconfigure(1, weight=1)
|
||||||
|
self.list_container_frame.rowconfigure(2, weight=1)
|
||||||
|
self.list_frame = ttk.LabelFrame(self.list_container_frame, text=_("Tunnels"))
|
||||||
|
self.list_frame.grid(column=0, row=0, sticky="nsew", padx=10, ipady=25)
|
||||||
|
# Listbox with Scrollbar
|
||||||
|
self.list_box = tk.Listbox(self.list_frame, selectmode="single")
|
||||||
|
self.list_box.config(
|
||||||
|
relief="flat",
|
||||||
|
font=("Ubuntu", 12, "bold"),
|
||||||
|
)
|
||||||
|
self.list_box.grid(column=0, row=0, sticky="nsew")
|
||||||
|
self.list_box.event_add("<<ClickEvent>>", "<Button-1>")
|
||||||
|
self.list_box.bind("<<ClickEvent>>", self.enable_check_box)
|
||||||
|
self.scrollbar = ttk.Scrollbar(
|
||||||
|
self.list_frame, orient="vertical", command=self.list_box.yview
|
||||||
|
)
|
||||||
|
self.scrollbar.grid(column=1, row=0, sticky="ns")
|
||||||
|
self.list_box.configure(yscrollcommand=self.scrollbar.set)
|
||||||
|
self.scrollbar.columnconfigure(1, weight=1)
|
||||||
|
self.scrollbar.rowconfigure(0, weight=1)
|
||||||
|
|
||||||
|
# Frame for Active Tunnel, Interface and Peer
|
||||||
|
# Right Side Frame
|
||||||
|
self.right_side_frame = ttk.Frame(self)
|
||||||
|
self.right_side_frame.grid(column=2, row=2, sticky="nsew")
|
||||||
|
self.right_side_frame.columnconfigure(2, weight=1)
|
||||||
|
self.right_side_frame.rowconfigure(2, weight=1)
|
||||||
|
|
||||||
# Show active Label
|
# Show active Label
|
||||||
self.select_tunnel = None
|
self.select_tunnel = None
|
||||||
self.lb = ttk.Label(self, text=_("Active: "))
|
self.active_frame = ttk.LabelFrame(
|
||||||
self.lb.config(font=("Ubuntu", 11, "bold"))
|
self.right_side_frame, text=_("Active Tunnel")
|
||||||
self.lb.grid(column=2, row=1, padx=15, pady=4, sticky="w")
|
)
|
||||||
|
|
||||||
|
self.active_frame.grid(
|
||||||
|
column=0, row=0, sticky="nsew", padx=10, pady=5, columnspan=3
|
||||||
|
)
|
||||||
|
self.active_frame.columnconfigure(0, weight=1)
|
||||||
|
self.active_frame.rowconfigure(0, weight=1)
|
||||||
|
# Interface Label Frame
|
||||||
|
self.interface_frame = ttk.LabelFrame(
|
||||||
|
self.right_side_frame, text=_("Interface")
|
||||||
|
)
|
||||||
|
self.interface_frame.grid(
|
||||||
|
column=0, row=1, sticky="nsew", padx=10, pady=5, columnspan=3
|
||||||
|
)
|
||||||
|
self.interface_frame.columnconfigure(0, weight=1)
|
||||||
|
self.interface_frame.rowconfigure(1, weight=1)
|
||||||
|
|
||||||
|
# Peer Label Frame
|
||||||
|
self.peer_frame = ttk.LabelFrame(self.right_side_frame, text=_("Peer"))
|
||||||
|
self.peer_frame.grid(
|
||||||
|
column=0, row=2, sticky="nsew", padx=10, pady=5, columnspan=3
|
||||||
|
)
|
||||||
|
self.peer_frame.columnconfigure(0, weight=1)
|
||||||
|
self.peer_frame.rowconfigure(2, weight=1)
|
||||||
|
|
||||||
|
# Auto Start Label Frame
|
||||||
|
self.autoconnect_frame = ttk.Frame(self)
|
||||||
|
self.autoconnect_frame.grid(column=0, row=3, columnspan=2, sticky="w")
|
||||||
|
|
||||||
|
# Rename Frame
|
||||||
|
self.rename_frame = ttk.Frame(self)
|
||||||
|
self.rename_frame.grid(column=2, padx=10, row=3, sticky="nsew")
|
||||||
|
self.rename_frame.columnconfigure(0, weight=2)
|
||||||
|
self.rename_frame.columnconfigure(1, weight=1)
|
||||||
|
|
||||||
# Label to Show active Tunnel
|
# Label to Show active Tunnel
|
||||||
self.str_var = tk.StringVar(value=self.a)
|
self.str_var = tk.StringVar(value=self.a)
|
||||||
self.color_label()
|
self.color_label()
|
||||||
|
|
||||||
# Interface Label
|
# Interface Label
|
||||||
self.interface = ttk.Label(self.lb_frame, text=_("Interface"))
|
self.interface = ttk.Label(self.interface_frame)
|
||||||
self.interface.grid(column=0, row=3, sticky="we", padx=120)
|
self.interface.grid(column=0, row=4, sticky="we")
|
||||||
self.interface.config(font=("Ubuntu", 9))
|
self.interface.config(font=("Ubuntu", 9))
|
||||||
|
|
||||||
# Peer Label
|
# Peer Label
|
||||||
self.peer = ttk.Label(self.lb_frame2, text=_("Peer"))
|
self.peer = ttk.Label(self.peer_frame)
|
||||||
self.peer.config(font=("Ubuntu", 9))
|
self.peer.config(font=("Ubuntu", 9))
|
||||||
self.peer.grid(column=0, row=4, sticky="we", padx=130)
|
self.peer.grid(column=0, row=5, sticky="we")
|
||||||
|
|
||||||
# Listbox with Scrollbar
|
|
||||||
self.l_box = tk.Listbox(self.lb_frame_btn_lbox, selectmode="single")
|
|
||||||
self.l_box.config(relief="ridge", font=("Ubuntu", 12, "bold"))
|
|
||||||
self.l_box.grid(column=1, rowspan=4, row=0, sticky="ns")
|
|
||||||
self.l_box.event_add("<<ClickEvent>>", "<Button-1>")
|
|
||||||
self.l_box.bind("<<ClickEvent>>", self.enable_check_box)
|
|
||||||
self.scrollbar = ttk.Scrollbar(
|
|
||||||
self.lb_frame_btn_lbox, orient="vertical", command=self.l_box.yview
|
|
||||||
)
|
|
||||||
self.scrollbar.grid(column=1, rowspan=4, row=0, sticky="nse")
|
|
||||||
self.l_box.configure(yscrollcommand=self.scrollbar.set)
|
|
||||||
|
|
||||||
# Tunnel List
|
# Tunnel List
|
||||||
self.tl = Tunnel.parse_files_to_dictionary(directory=AppConfig.TEMP_DIR)
|
self.tl = Tunnel.parse_files_to_dictionary(directory=AppConfig.TEMP_DIR)
|
||||||
@ -246,8 +325,8 @@ class FrameWidgets(ttk.Frame):
|
|||||||
AppConfig.ensure_directories()
|
AppConfig.ensure_directories()
|
||||||
|
|
||||||
for tunnels, values in self.tl.items():
|
for tunnels, values in self.tl.items():
|
||||||
self.l_box.insert("end", tunnels)
|
self.list_box.insert("end", tunnels)
|
||||||
self.l_box.update()
|
self.list_box.update()
|
||||||
|
|
||||||
# Button Vpn
|
# Button Vpn
|
||||||
if self.a != "":
|
if self.a != "":
|
||||||
@ -266,52 +345,55 @@ class FrameWidgets(ttk.Frame):
|
|||||||
|
|
||||||
# Button Import
|
# Button Import
|
||||||
self.btn_i = ttk.Button(
|
self.btn_i = ttk.Button(
|
||||||
self.lb_frame_btn_lbox,
|
self.control_buttons_frame,
|
||||||
image=self.imp_pic,
|
image=self.image_manager.load_image("icon_import"),
|
||||||
command=self.import_sl,
|
command=self.import_sl,
|
||||||
padding=0,
|
padding=0,
|
||||||
)
|
)
|
||||||
self.btn_i.grid(column=0, row=1, padx=15, pady=8)
|
self.btn_i.grid(column=0, row=1, pady=8)
|
||||||
|
|
||||||
Tooltip(self.btn_i, Msg.TTIP["import_tl"], self.tooltip_state)
|
Tooltip(self.btn_i, Msg.TTIP["import_tl"], self.tooltip_state)
|
||||||
|
|
||||||
# Button Trash
|
# Button Trash
|
||||||
self.btn_tr = ttk.Button(
|
self.btn_tr = ttk.Button(
|
||||||
self.lb_frame_btn_lbox,
|
self.control_buttons_frame,
|
||||||
image=self.tr_pic,
|
image=self.image_manager.load_image("icon_trash"),
|
||||||
command=self.delete,
|
command=self.delete,
|
||||||
padding=0,
|
padding=0,
|
||||||
style="CButton.TButton",
|
|
||||||
)
|
)
|
||||||
self.btn_tr.grid(column=0, row=2, padx=15, pady=8)
|
self.btn_tr.grid(column=0, row=2, pady=8)
|
||||||
|
|
||||||
if self.l_box.size() == 0:
|
if self.list_box.size() == 0:
|
||||||
Tooltip(self.btn_tr, Msg.TTIP["trash_tl_info"], self.tooltip_state)
|
Tooltip(self.btn_tr, Msg.TTIP["trash_tl_info"], self.tooltip_state)
|
||||||
else:
|
else:
|
||||||
Tooltip(self.btn_tr, Msg.TTIP["trash_tl"], self.tooltip_state)
|
Tooltip(self.btn_tr, Msg.TTIP["trash_tl"], self.tooltip_state)
|
||||||
|
|
||||||
# Button Export
|
# Button Export
|
||||||
self.btn_exp = ttk.Button(
|
self.btn_exp = ttk.Button(
|
||||||
self.lb_frame_btn_lbox,
|
self.control_buttons_frame,
|
||||||
image=self.exp_pic,
|
image=self.image_manager.load_image("icon_export"),
|
||||||
command=lambda: Tunnel.export(),
|
command=lambda: Tunnel.export(),
|
||||||
padding=0,
|
padding=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.btn_exp.grid(column=0, row=3, padx=15, pady=8)
|
self.btn_exp.grid(column=0, row=3, pady=8)
|
||||||
|
self.btn_exp.columnconfigure(0, weight=1)
|
||||||
|
self.btn_exp.rowconfigure(3, weight=1)
|
||||||
|
|
||||||
if self.l_box.size() == 0:
|
if self.list_box.size() == 0:
|
||||||
Tooltip(self.btn_exp, Msg.TTIP["export_tl_info"], self.tooltip_state)
|
Tooltip(self.btn_exp, Msg.TTIP["export_tl_info"], self.tooltip_state)
|
||||||
else:
|
else:
|
||||||
Tooltip(self.btn_exp, Msg.TTIP["export_tl"], self.tooltip_state)
|
Tooltip(self.btn_exp, Msg.TTIP["export_tl"], self.tooltip_state)
|
||||||
|
|
||||||
# Label Entry
|
# Label Entry
|
||||||
self.lb_rename = ttk.Entry(self.lb_frame4, width=20)
|
self.lb_rename = ttk.Entry(self.rename_frame)
|
||||||
self.lb_rename.grid(column=2, row=0, padx=8, pady=10, sticky="ne")
|
self.lb_rename.grid(column=0, row=0, padx=8, pady=10, sticky="ne")
|
||||||
|
self.lb_rename.config(width=15)
|
||||||
|
|
||||||
self.lb_rename.insert(0, _("Max. 12 characters!"))
|
self.lb_rename.insert(0, _("Max. 12 characters!"))
|
||||||
self.lb_rename.config(state="disable")
|
self.lb_rename.config(state="disable")
|
||||||
|
|
||||||
if self.l_box.size() != 0:
|
if self.list_box.size() != 0:
|
||||||
Tooltip(
|
Tooltip(
|
||||||
self.lb_rename,
|
self.lb_rename,
|
||||||
Msg.TTIP["rename_tl"],
|
Msg.TTIP["rename_tl"],
|
||||||
@ -330,14 +412,13 @@ class FrameWidgets(ttk.Frame):
|
|||||||
|
|
||||||
# Button Rename
|
# Button Rename
|
||||||
self.btn_rename = ttk.Button(
|
self.btn_rename = ttk.Button(
|
||||||
self.lb_frame4,
|
self.rename_frame,
|
||||||
text=_("Rename"),
|
text=_("Rename"),
|
||||||
state="disable",
|
state="disable",
|
||||||
command=self.tl_rename,
|
command=self.tl_rename,
|
||||||
padding=4,
|
width=15,
|
||||||
style="RnButton.TButton",
|
|
||||||
)
|
)
|
||||||
self.btn_rename.grid(column=3, row=0, padx=5, pady=10, sticky="ne")
|
self.btn_rename.grid(column=1, row=0, pady=10, sticky="nsew")
|
||||||
|
|
||||||
# Check Buttons
|
# Check Buttons
|
||||||
self.selected_option = tk.IntVar()
|
self.selected_option = tk.IntVar()
|
||||||
@ -346,19 +427,21 @@ class FrameWidgets(ttk.Frame):
|
|||||||
|
|
||||||
# Frame for Labels, Entry and Button
|
# Frame for Labels, Entry and Button
|
||||||
self.autoconnect = ttk.Label(
|
self.autoconnect = ttk.Label(
|
||||||
self.lb_frame3, textvariable=self.autoconnect_var, width=15
|
self.autoconnect_frame, textvariable=self.autoconnect_var
|
||||||
)
|
)
|
||||||
self.autoconnect.config(font=("Ubuntu", 11))
|
self.autoconnect.config(font=("Ubuntu", 11))
|
||||||
self.autoconnect.grid(column=1, row=0, sticky="e", pady=19)
|
self.autoconnect.grid(column=1, row=0, pady=10, sticky="nsew")
|
||||||
|
self.autoconnect.columnconfigure(1, weight=1)
|
||||||
|
self.autoconnect.rowconfigure(0, weight=1)
|
||||||
self.wg_autostart = ttk.Checkbutton(
|
self.wg_autostart = ttk.Checkbutton(
|
||||||
self.lb_frame3,
|
self.autoconnect_frame,
|
||||||
text=_("Autoconnect on:"),
|
text=_("Autoconnect on:"),
|
||||||
variable=self.selected_option,
|
variable=self.selected_option,
|
||||||
command=self.box_set,
|
command=self.box_set,
|
||||||
)
|
)
|
||||||
self.wg_autostart.grid(column=0, row=0, pady=15, padx=15, sticky="nw")
|
self.wg_autostart.grid(column=0, row=0, pady=10, padx=(10, 0), sticky="ew")
|
||||||
|
|
||||||
if self.l_box.size() >= 1 and len(self.l_box.curselection()) >= 1:
|
if self.list_box.size() >= 1 and len(self.list_box.curselection()) >= 1:
|
||||||
Tooltip(
|
Tooltip(
|
||||||
self.wg_autostart,
|
self.wg_autostart,
|
||||||
Msg.TTIP["autostart"],
|
Msg.TTIP["autostart"],
|
||||||
@ -367,7 +450,7 @@ class FrameWidgets(ttk.Frame):
|
|||||||
y_offset=-40,
|
y_offset=-40,
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.l_box.size() == 0:
|
if self.list_box.size() == 0:
|
||||||
Tooltip(
|
Tooltip(
|
||||||
self.wg_autostart,
|
self.wg_autostart,
|
||||||
Msg.TTIP["autostart_info"],
|
Msg.TTIP["autostart_info"],
|
||||||
@ -400,6 +483,15 @@ class FrameWidgets(ttk.Frame):
|
|||||||
else:
|
else:
|
||||||
self.updates_lb.grid_remove()
|
self.updates_lb.grid_remove()
|
||||||
|
|
||||||
|
def updater(self):
|
||||||
|
"""Start the lxtools_installer"""
|
||||||
|
tmp_dir = Path("/tmp/lxtools")
|
||||||
|
Path.mkdir(tmp_dir, exist_ok=True)
|
||||||
|
os.chdir(tmp_dir)
|
||||||
|
result = subprocess.run(["/usr/local/bin/lxtools_installer"], check=False)
|
||||||
|
if result.returncode != 0:
|
||||||
|
MessageDialog("error", result.stderr)
|
||||||
|
|
||||||
# Update the labels based on the result
|
# Update the labels based on the result
|
||||||
def update_ui_for_update(self, res):
|
def update_ui_for_update(self, res):
|
||||||
"""Update UI elements based on an update check result"""
|
"""Update UI elements based on an update check result"""
|
||||||
@ -436,25 +528,20 @@ class FrameWidgets(ttk.Frame):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
self.set_update.set(value=0)
|
self.set_update.set(value=0)
|
||||||
update_text = f"Update {res} {_('available!')}"
|
|
||||||
|
|
||||||
# Clear the label text since we'll show the button instead
|
# Clear the label text since we'll show the button instead
|
||||||
self.update_label.set("")
|
self.update_label.set("")
|
||||||
|
|
||||||
# Create the update button
|
# Create the update button
|
||||||
self.update_btn = ttk.Menubutton(self.menu_frame, text=update_text)
|
self.update_btn = ttk.Button(
|
||||||
self.update_btn.grid(column=4, columnspan=3, row=0, padx=0)
|
self.menu_frame,
|
||||||
Tooltip(
|
image=self.image_manager.load_image("update"),
|
||||||
self.update_btn, _("Click to download new version"), self.tooltip_state
|
style="Toolbutton",
|
||||||
|
command=self.updater,
|
||||||
)
|
)
|
||||||
|
self.update_btn.grid(column=5, row=0, padx=0)
|
||||||
self.download = tk.Menu(self, relief="flat")
|
Tooltip(
|
||||||
self.update_btn.configure(menu=self.download, style="Toolbutton")
|
self.update_btn, _("Click to install new version"), self.tooltip_state
|
||||||
self.download.add_command(
|
|
||||||
label=_("Download"),
|
|
||||||
command=lambda: GiteaUpdate.download(
|
|
||||||
f"{AppConfig.DOWNLOAD_URL}/{res}.zip", res
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -462,10 +549,6 @@ class FrameWidgets(ttk.Frame):
|
|||||||
"""
|
"""
|
||||||
a tk.Toplevel window
|
a tk.Toplevel window
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def link_btn() -> None:
|
|
||||||
webbrowser.open("https://git.ilunix.de/punix/Wire-Py")
|
|
||||||
|
|
||||||
msg_t = _(
|
msg_t = _(
|
||||||
"Wire-Py a simple Wireguard Gui for Linux systems.\n\n"
|
"Wire-Py a simple Wireguard Gui for Linux systems.\n\n"
|
||||||
"Wire-Py is open source software written in Python.\n\n"
|
"Wire-Py is open source software written in Python.\n\n"
|
||||||
@ -473,13 +556,17 @@ class FrameWidgets(ttk.Frame):
|
|||||||
"Use without warranty!\n"
|
"Use without warranty!\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
LxTools.msg_window(
|
MessageDialog(
|
||||||
AppConfig.IMAGE_PATHS["icon_vpn"],
|
"info",
|
||||||
AppConfig.IMAGE_PATHS["icon_vpn"],
|
|
||||||
_("Info"),
|
|
||||||
msg_t,
|
msg_t,
|
||||||
_("Go to Wire-Py git"),
|
buttons=["OK", _("Go to Wire-Py git")],
|
||||||
link_btn,
|
title=_("Info"),
|
||||||
|
commands=[
|
||||||
|
None,
|
||||||
|
partial(webbrowser.open, "https://git.ilunix.de/punix/Wire-Py"),
|
||||||
|
],
|
||||||
|
icon="/usr/share/icons/lx-icons/64/wg_vpn.png",
|
||||||
|
wraplength=420,
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_setting(self, update_res) -> None:
|
def update_setting(self, update_res) -> None:
|
||||||
@ -561,7 +648,9 @@ class FrameWidgets(ttk.Frame):
|
|||||||
new_theme = "dark" if current_theme == "light" else "light"
|
new_theme = "dark" if current_theme == "light" else "light"
|
||||||
ThemeManager.change_theme(self, new_theme, new_theme)
|
ThemeManager.change_theme(self, new_theme, new_theme)
|
||||||
self.color_label()
|
self.color_label()
|
||||||
|
self.header_label.config(fg="#ffffff")
|
||||||
self.update_theme_label() # Update the theme label
|
self.update_theme_label() # Update the theme label
|
||||||
|
|
||||||
# Update Menulfield
|
# Update Menulfield
|
||||||
self.settings.entryconfigure(2, label=self.theme_label.get())
|
self.settings.entryconfigure(2, label=self.theme_label.get())
|
||||||
|
|
||||||
@ -570,14 +659,16 @@ class FrameWidgets(ttk.Frame):
|
|||||||
Start Button
|
Start Button
|
||||||
"""
|
"""
|
||||||
self.btn_stst = ttk.Button(
|
self.btn_stst = ttk.Button(
|
||||||
self.lb_frame_btn_lbox,
|
self.control_buttons_frame,
|
||||||
image=self.wg_vpn_start,
|
image=self.image_manager.load_image("icon_start"),
|
||||||
command=lambda: self.wg_switch("start"),
|
command=lambda: self.wg_switch("start"),
|
||||||
padding=0,
|
padding=0,
|
||||||
)
|
)
|
||||||
self.btn_stst.grid(column=0, row=0, padx=5, pady=8)
|
self.btn_stst.grid(column=0, row=0, pady=8)
|
||||||
|
self.btn_stst.columnconfigure(0, weight=1)
|
||||||
|
self.btn_stst.rowconfigure(0, weight=1)
|
||||||
|
|
||||||
if self.l_box.size() == 0:
|
if self.list_box.size() == 0:
|
||||||
Tooltip(self.btn_stst, Msg.TTIP["empty_list"], self.tooltip_state)
|
Tooltip(self.btn_stst, Msg.TTIP["empty_list"], self.tooltip_state)
|
||||||
else:
|
else:
|
||||||
Tooltip(self.btn_stst, Msg.TTIP["start_tl"], self.tooltip_state)
|
Tooltip(self.btn_stst, Msg.TTIP["start_tl"], self.tooltip_state)
|
||||||
@ -589,28 +680,32 @@ class FrameWidgets(ttk.Frame):
|
|||||||
if ConfigManager.get("theme") == "light":
|
if ConfigManager.get("theme") == "light":
|
||||||
|
|
||||||
self.lb_tunnel = ttk.Label(
|
self.lb_tunnel = ttk.Label(
|
||||||
self, textvariable=self.str_var, foreground="green"
|
self.active_frame, textvariable=self.str_var, foreground="green"
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.lb_tunnel = ttk.Label(
|
self.lb_tunnel = ttk.Label(
|
||||||
self, textvariable=self.str_var, foreground="yellow"
|
self.active_frame, textvariable=self.str_var, foreground="yellow"
|
||||||
)
|
)
|
||||||
|
|
||||||
self.lb_tunnel.config(font=("Ubuntu", 11, "bold"))
|
self.lb_tunnel.config(font=("Ubuntu", 11, "bold"))
|
||||||
self.lb_tunnel.grid(column=2, padx=10, row=1)
|
self.lb_tunnel.grid(column=0, row=0, padx=10, pady=(0, 10), sticky="n")
|
||||||
|
self.lb_tunnel.columnconfigure(0, weight=1)
|
||||||
|
self.lb_tunnel.rowconfigure(0, weight=1)
|
||||||
|
|
||||||
def stop(self) -> None:
|
def stop(self) -> None:
|
||||||
"""
|
"""
|
||||||
Stop Button
|
Stop Button
|
||||||
"""
|
"""
|
||||||
self.btn_stst = ttk.Button(
|
self.btn_stst = ttk.Button(
|
||||||
self.lb_frame_btn_lbox,
|
self.control_buttons_frame,
|
||||||
image=self.wg_vpn_stop,
|
image=self.image_manager.load_image("icon_stop"),
|
||||||
command=lambda: self.wg_switch("stop"),
|
command=lambda: self.wg_switch("stop"),
|
||||||
padding=0,
|
padding=0,
|
||||||
)
|
)
|
||||||
self.btn_stst.grid(column=0, row=0, padx=5, pady=8)
|
self.btn_stst.grid(column=0, row=0, pady=8)
|
||||||
|
self.btn_stst.columnconfigure(0, weight=1)
|
||||||
|
self.btn_stst.rowconfigure(0, weight=1)
|
||||||
|
|
||||||
Tooltip(self.btn_stst, Msg.TTIP["stop_tl"], self.tooltip_state)
|
Tooltip(self.btn_stst, Msg.TTIP["stop_tl"], self.tooltip_state)
|
||||||
|
|
||||||
@ -634,22 +729,16 @@ class FrameWidgets(ttk.Frame):
|
|||||||
)
|
)
|
||||||
data_import, key_name = Tunnel.parse_files_to_dictionary(filepath=filepath)
|
data_import, key_name = Tunnel.parse_files_to_dictionary(filepath=filepath)
|
||||||
|
|
||||||
if CryptoUtil.find_key(f"{data_import[key_name]["PrivateKey"]}="):
|
if CryptoUtil.find_key(f"{data_import[key_name]['PrivateKey']}="):
|
||||||
LxTools.msg_window(
|
MessageDialog("error", Msg.STR["tl_exist"], title=Msg.STR["imp_err"])
|
||||||
AppConfig.IMAGE_PATHS["icon_error"],
|
|
||||||
AppConfig.IMAGE_PATHS["icon_msg"],
|
|
||||||
Msg.STR["imp_err"],
|
|
||||||
Msg.STR["tl_exist"],
|
|
||||||
)
|
|
||||||
|
|
||||||
elif not CryptoUtil.is_valid_base64(
|
elif not CryptoUtil.is_valid_base64(
|
||||||
f"{data_import[key_name]["PrivateKey"]}="
|
f"{data_import[key_name]['PrivateKey']}="
|
||||||
): # 2. Second check: Is it valid Base64?
|
): # 2. Second check: Is it valid Base64?
|
||||||
LxTools.msg_window(
|
MessageDialog(
|
||||||
AppConfig.IMAGE_PATHS["icon_error"],
|
"error",
|
||||||
AppConfig.IMAGE_PATHS["icon_msg"],
|
|
||||||
Msg.STR["imp_err"],
|
|
||||||
Msg.STR["invalid_base64"],
|
Msg.STR["invalid_base64"],
|
||||||
|
title=Msg.STR["imp_err"],
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
filepath = Path(filepath)
|
filepath = Path(filepath)
|
||||||
@ -704,11 +793,11 @@ class FrameWidgets(ttk.Frame):
|
|||||||
AppConfig.ensure_directories()
|
AppConfig.ensure_directories()
|
||||||
self.str_var.set("")
|
self.str_var.set("")
|
||||||
self.a = Tunnel.get_active()
|
self.a = Tunnel.get_active()
|
||||||
self.l_box.insert(0, self.a)
|
self.list_box.insert(0, self.a)
|
||||||
self.wg_autostart.configure(state="normal")
|
self.wg_autostart.configure(state="normal")
|
||||||
self.l_box.selection_clear(0, tk.END)
|
self.list_box.selection_clear(0, tk.END)
|
||||||
self.l_box.update()
|
self.list_box.update()
|
||||||
self.l_box.selection_set(0)
|
self.list_box.selection_set(0)
|
||||||
|
|
||||||
Tooltip(
|
Tooltip(
|
||||||
self.wg_autostart,
|
self.wg_autostart,
|
||||||
@ -742,12 +831,7 @@ class FrameWidgets(ttk.Frame):
|
|||||||
print(f">> {import_file.stem} << autostart is disabled by default")
|
print(f">> {import_file.stem} << autostart is disabled by default")
|
||||||
|
|
||||||
except UnboundLocalError:
|
except UnboundLocalError:
|
||||||
LxTools.msg_window(
|
MessageDialog("error", Msg.STR["no_valid_file"], title=Msg.STR["imp_err"])
|
||||||
AppConfig.IMAGE_PATHS["icon_error"],
|
|
||||||
AppConfig.IMAGE_PATHS["icon_msg"],
|
|
||||||
Msg.STR["imp_err"],
|
|
||||||
Msg.STR["no_valid_file"],
|
|
||||||
)
|
|
||||||
except (IsADirectoryError, TypeError, FileNotFoundError):
|
except (IsADirectoryError, TypeError, FileNotFoundError):
|
||||||
print("File import: abort by user...")
|
print("File import: abort by user...")
|
||||||
except EOFError as e:
|
except EOFError as e:
|
||||||
@ -758,8 +842,8 @@ class FrameWidgets(ttk.Frame):
|
|||||||
delete Wireguard Tunnel
|
delete Wireguard Tunnel
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.select_tunnel = self.l_box.curselection()
|
self.select_tunnel = self.list_box.curselection()
|
||||||
select_tl = self.l_box.get(self.select_tunnel[0])
|
select_tl = self.list_box.get(self.select_tunnel[0])
|
||||||
|
|
||||||
process: CompletedProcess[str] = run(
|
process: CompletedProcess[str] = run(
|
||||||
["nmcli", "connection", "delete", select_tl],
|
["nmcli", "connection", "delete", select_tl],
|
||||||
@ -773,7 +857,7 @@ class FrameWidgets(ttk.Frame):
|
|||||||
f"{process.stderr} Code: {process.returncode}", exc_info=True
|
f"{process.stderr} Code: {process.returncode}", exc_info=True
|
||||||
)
|
)
|
||||||
|
|
||||||
self.l_box.delete(self.select_tunnel[0])
|
self.list_box.delete(self.select_tunnel[0])
|
||||||
Path.unlink(f"{AppConfig.CONFIG_DIR}/{select_tl}.dat")
|
Path.unlink(f"{AppConfig.CONFIG_DIR}/{select_tl}.dat")
|
||||||
|
|
||||||
if select_tl == ConfigManager.get("autostart"):
|
if select_tl == ConfigManager.get("autostart"):
|
||||||
@ -784,7 +868,7 @@ class FrameWidgets(ttk.Frame):
|
|||||||
self.wg_autostart.configure(state="disabled")
|
self.wg_autostart.configure(state="disabled")
|
||||||
|
|
||||||
# for disabling checkbox when Listbox empty
|
# for disabling checkbox when Listbox empty
|
||||||
if self.l_box.size() == 0:
|
if self.list_box.size() == 0:
|
||||||
self.wg_autostart.configure(state="disabled")
|
self.wg_autostart.configure(state="disabled")
|
||||||
self.lb_rename.configure(state="disabled")
|
self.lb_rename.configure(state="disabled")
|
||||||
Tooltip(
|
Tooltip(
|
||||||
@ -803,35 +887,25 @@ class FrameWidgets(ttk.Frame):
|
|||||||
if self.a != "" and self.a == select_tl:
|
if self.a != "" and self.a == select_tl:
|
||||||
self.str_var.set(value="")
|
self.str_var.set(value="")
|
||||||
self.start()
|
self.start()
|
||||||
self.l_box.update()
|
self.list_box.update()
|
||||||
self.reset_fields()
|
self.reset_fields()
|
||||||
|
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
|
||||||
if self.l_box.size() != 0:
|
if self.list_box.size() != 0:
|
||||||
|
|
||||||
LxTools.msg_window(
|
MessageDialog("info", Msg.STR["sel_list"], title=Msg.STR["sel_tl"])
|
||||||
AppConfig.IMAGE_PATHS["icon_info"],
|
|
||||||
AppConfig.IMAGE_PATHS["icon_msg"],
|
|
||||||
Msg.STR["sel_tl"],
|
|
||||||
Msg.STR["sel_list"],
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
LxTools.msg_window(
|
MessageDialog("info", Msg.STR["tl_first"], title=Msg.STR["sel_tl"])
|
||||||
AppConfig.IMAGE_PATHS["icon_info"],
|
|
||||||
AppConfig.IMAGE_PATHS["icon_msg"],
|
|
||||||
Msg.STR["sel_tl"],
|
|
||||||
Msg.STR["tl_first"],
|
|
||||||
)
|
|
||||||
|
|
||||||
def enable_check_box(self, _) -> None:
|
def enable_check_box(self, _) -> None:
|
||||||
"""
|
"""
|
||||||
checkbox for enable autostart Tunnel
|
checkbox for enable autostart Tunnel
|
||||||
"""
|
"""
|
||||||
AppConfig.get_autostart_content()
|
AppConfig.get_autostart_content()
|
||||||
if self.l_box.size() != 0:
|
if self.list_box.size() != 0:
|
||||||
self.wg_autostart.configure(state="normal")
|
self.wg_autostart.configure(state="normal")
|
||||||
self.lb_rename.config(state="normal")
|
self.lb_rename.config(state="normal")
|
||||||
self.lb_rename.delete(0, tk.END)
|
self.lb_rename.delete(0, tk.END)
|
||||||
@ -858,13 +932,14 @@ class FrameWidgets(ttk.Frame):
|
|||||||
self.autoconnect_var.set(self.auto_con)
|
self.autoconnect_var.set(self.auto_con)
|
||||||
|
|
||||||
self.autoconnect = ttk.Label(
|
self.autoconnect = ttk.Label(
|
||||||
self.lb_frame3,
|
self.autoconnect_frame,
|
||||||
textvariable=self.autoconnect_var,
|
textvariable=self.autoconnect_var,
|
||||||
foreground="#0071ff",
|
foreground="#0071ff",
|
||||||
width=15,
|
width=18,
|
||||||
)
|
)
|
||||||
self.autoconnect.config(font=("Ubuntu", 11))
|
self.autoconnect.config(font=("Ubuntu", 11))
|
||||||
self.autoconnect.grid(column=1, row=0, sticky="e", pady=19)
|
self.autoconnect.grid(column=1, row=0, sticky="ew", pady=19)
|
||||||
|
self.autoconnect.rowconfigure(0, weight=1)
|
||||||
|
|
||||||
def box_set(self) -> None:
|
def box_set(self) -> None:
|
||||||
"""
|
"""
|
||||||
@ -878,13 +953,13 @@ class FrameWidgets(ttk.Frame):
|
|||||||
to disable the autostart.
|
to disable the autostart.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
select_tunnel = self.l_box.curselection()
|
select_tunnel = self.list_box.curselection()
|
||||||
select_tl = self.l_box.get(select_tunnel[0])
|
select_tl = self.list_box.get(select_tunnel[0])
|
||||||
|
|
||||||
if self.selected_option.get() == 0:
|
if self.selected_option.get() == 0:
|
||||||
ConfigManager.set("autostart", "off")
|
ConfigManager.set("autostart", "off")
|
||||||
|
|
||||||
if self.l_box.size() == 0:
|
if self.list_box.size() == 0:
|
||||||
self.wg_autostart.configure(state="disabled")
|
self.wg_autostart.configure(state="disabled")
|
||||||
|
|
||||||
if self.selected_option.get() >= 1:
|
if self.selected_option.get() >= 1:
|
||||||
@ -907,47 +982,27 @@ class FrameWidgets(ttk.Frame):
|
|||||||
|
|
||||||
if len(self.lb_rename.get()) > 12:
|
if len(self.lb_rename.get()) > 12:
|
||||||
|
|
||||||
LxTools.msg_window(
|
MessageDialog("info", Msg.STR["sign_len"], title=Msg.STR["ren_err"])
|
||||||
AppConfig.IMAGE_PATHS["icon_info"],
|
|
||||||
AppConfig.IMAGE_PATHS["icon_msg"],
|
|
||||||
Msg.STR["ren_err"],
|
|
||||||
Msg.STR["sign_len"],
|
|
||||||
)
|
|
||||||
|
|
||||||
elif len(self.lb_rename.get()) == 0:
|
elif len(self.lb_rename.get()) == 0:
|
||||||
|
|
||||||
LxTools.msg_window(
|
MessageDialog("info", Msg.STR["zero_signs"], title=Msg.STR["ren_err"])
|
||||||
AppConfig.IMAGE_PATHS["icon_info"],
|
|
||||||
AppConfig.IMAGE_PATHS["icon_msg"],
|
|
||||||
Msg.STR["ren_err"],
|
|
||||||
Msg.STR["zero_signs"],
|
|
||||||
)
|
|
||||||
|
|
||||||
elif any(ch in special_characters for ch in self.lb_rename.get()):
|
elif any(ch in special_characters for ch in self.lb_rename.get()):
|
||||||
|
|
||||||
LxTools.msg_window(
|
MessageDialog("info", Msg.STR["false_signs"], title=Msg.STR["ren_err"])
|
||||||
AppConfig.IMAGE_PATHS["icon_info"],
|
|
||||||
AppConfig.IMAGE_PATHS["icon_msg"],
|
|
||||||
Msg.STR["ren_err"],
|
|
||||||
Msg.STR["false_signs"],
|
|
||||||
)
|
|
||||||
|
|
||||||
elif self.lb_rename.get() in [
|
elif self.lb_rename.get() in [
|
||||||
file.stem for file in AppConfig.CONFIG_DIR.glob("*.dat")
|
file.stem for file in AppConfig.CONFIG_DIR.glob("*.dat")
|
||||||
]:
|
]:
|
||||||
|
|
||||||
LxTools.msg_window(
|
MessageDialog("info", Msg.STR["is_in_use"], title=Msg.STR["ren_err"])
|
||||||
AppConfig.IMAGE_PATHS["icon_info"],
|
|
||||||
AppConfig.IMAGE_PATHS["icon_msg"],
|
|
||||||
Msg.STR["ren_err"],
|
|
||||||
Msg.STR["is_in_use"],
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.select_tunnel = self.l_box.curselection()
|
self.select_tunnel = self.list_box.curselection()
|
||||||
select_tl = self.l_box.get(self.select_tunnel[0])
|
select_tl = self.list_box.get(self.select_tunnel[0])
|
||||||
|
|
||||||
# nmcli connection modify old connection.id iphone
|
# nmcli connection modify old connection.id iphone
|
||||||
process: CompletedProcess[str] = run(
|
process: CompletedProcess[str] = run(
|
||||||
@ -975,20 +1030,15 @@ class FrameWidgets(ttk.Frame):
|
|||||||
if select_tl == ConfigManager.get("autostart"):
|
if select_tl == ConfigManager.get("autostart"):
|
||||||
ConfigManager.set("autostart", self.lb_rename.get())
|
ConfigManager.set("autostart", self.lb_rename.get())
|
||||||
self.autoconnect_var.set(value=self.lb_rename.get())
|
self.autoconnect_var.set(value=self.lb_rename.get())
|
||||||
self.l_box.delete(self.select_tunnel[0])
|
self.list_box.delete(self.select_tunnel[0])
|
||||||
self.l_box.insert("end", self.lb_rename.get())
|
self.list_box.insert("end", self.lb_rename.get())
|
||||||
self.l_box.update()
|
self.list_box.update()
|
||||||
self.lb_rename.delete(0, tk.END)
|
self.lb_rename.delete(0, tk.END)
|
||||||
self.update_connection_display()
|
self.update_connection_display()
|
||||||
|
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
|
||||||
LxTools.msg_window(
|
MessageDialog("info", Msg.STR["sel_list"], title=Msg.STR["ren_err"])
|
||||||
AppConfig.IMAGE_PATHS["icon_info"],
|
|
||||||
AppConfig.IMAGE_PATHS["icon_msg"],
|
|
||||||
Msg.STR["ren_err"],
|
|
||||||
Msg.STR["sel_list"],
|
|
||||||
)
|
|
||||||
|
|
||||||
except EOFError as e:
|
except EOFError as e:
|
||||||
logging.error(e, exc_info=True)
|
logging.error(e, exc_info=True)
|
||||||
@ -1013,34 +1063,36 @@ class FrameWidgets(ttk.Frame):
|
|||||||
in the UI using ttk.Label widgets.
|
in the UI using ttk.Label widgets.
|
||||||
Creates three labels for address, DNS, and endpoint with
|
Creates three labels for address, DNS, and endpoint with
|
||||||
specific styling (color, font), positioning them in a
|
specific styling (color, font), positioning them in a
|
||||||
grid layout (`lb_frame` and `lb_frame2`).
|
grid layout (`lb_frame` and `peer_frame`).
|
||||||
Each label is linked to a corresponding text variable
|
Each label is linked to a corresponding text variable
|
||||||
(`self.add`, `self.DNS`, `self.enp`) for dynamic data updates.
|
(`self.add`, `self.DNS`, `self.enp`) for dynamic data updates.
|
||||||
"""
|
"""
|
||||||
# Address Label
|
# Address Label
|
||||||
self.address = ttk.Label(
|
self.address = ttk.Label(
|
||||||
self.lb_frame, textvariable=self.add, foreground="#0071ff"
|
self.interface_frame, textvariable=self.add, foreground="#0071ff"
|
||||||
)
|
)
|
||||||
self.address.grid(column=0, row=5, sticky="w", padx=10, pady=6)
|
self.address.grid(column=0, row=5, sticky="w", padx=10, pady=(0, 20))
|
||||||
self.address.config(font=("Ubuntu", 9))
|
self.address.config(font=("Ubuntu", 9))
|
||||||
|
|
||||||
# DNS Label
|
# DNS Label
|
||||||
self.dns = ttk.Label(self.lb_frame, textvariable=self.DNS, foreground="#0071ff")
|
self.dns = ttk.Label(
|
||||||
self.dns.grid(column=0, row=7, sticky="w", padx=10, pady=6)
|
self.interface_frame, textvariable=self.DNS, foreground="#0071ff"
|
||||||
|
)
|
||||||
|
self.dns.grid(column=0, row=7, sticky="w", padx=10, pady=(0, 20))
|
||||||
self.dns.config(font=("Ubuntu", 9))
|
self.dns.config(font=("Ubuntu", 9))
|
||||||
|
|
||||||
# Endpoint Label
|
# Endpoint Label
|
||||||
self.endpoint = ttk.Label(
|
self.endpoint = ttk.Label(
|
||||||
self.lb_frame2, textvariable=self.enp, foreground="#0071ff"
|
self.peer_frame, textvariable=self.enp, foreground="#0071ff"
|
||||||
)
|
)
|
||||||
self.endpoint.grid(column=0, row=8, sticky="w", padx=10, pady=20)
|
self.endpoint.grid(column=0, row=8, sticky="w", padx=10, pady=(0, 30))
|
||||||
self.endpoint.config(font=("Ubuntu", 9))
|
self.endpoint.config(font=("Ubuntu", 9))
|
||||||
|
|
||||||
def wg_switch(self, event=None) -> None:
|
def wg_switch(self, event=None) -> None:
|
||||||
"""
|
"""
|
||||||
Manages switching between active and inactiveVPN connections.
|
Manages switching between active and inactiveVPN connections.
|
||||||
If no tunnel is selected (`self.a == ""`), it starts a new connection
|
If no tunnel is selected (`self.a == ""`), it starts a new connection
|
||||||
with the selected tunnel from the listbox (`l_box`).
|
with the selected tunnel from the listbox (`list_box`).
|
||||||
Otherwise, it stops the current connection and updates
|
Otherwise, it stops the current connection and updates
|
||||||
tunnel data using `handle_tunnel_data`.
|
tunnel data using `handle_tunnel_data`.
|
||||||
Handles errors like `IndexError` by displaying appropriate
|
Handles errors like `IndexError` by displaying appropriate
|
||||||
@ -1048,8 +1100,8 @@ class FrameWidgets(ttk.Frame):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if self.a == "":
|
if self.a == "":
|
||||||
self.select_tunnel = self.l_box.curselection()
|
self.select_tunnel = self.list_box.curselection()
|
||||||
select_tl = self.l_box.get(self.select_tunnel[0])
|
select_tl = self.list_box.get(self.select_tunnel[0])
|
||||||
self.handle_connection_state("start", select_tl)
|
self.handle_connection_state("start", select_tl)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -1059,23 +1111,13 @@ class FrameWidgets(ttk.Frame):
|
|||||||
|
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
|
||||||
if self.l_box.size() != 0:
|
if self.list_box.size() != 0:
|
||||||
|
|
||||||
LxTools.msg_window(
|
MessageDialog("info", Msg.STR["sel_list"], title=Msg.STR["sel_tl"])
|
||||||
AppConfig.IMAGE_PATHS["icon_info"],
|
|
||||||
AppConfig.IMAGE_PATHS["icon_msg"],
|
|
||||||
Msg.STR["sel_tl"],
|
|
||||||
Msg.STR["sel_list"],
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
LxTools.msg_window(
|
MessageDialog("info", Msg.STR["tl_first"], title=Msg.STR["sel_tl"])
|
||||||
AppConfig.IMAGE_PATHS["icon_info"],
|
|
||||||
AppConfig.IMAGE_PATHS["icon_msg"],
|
|
||||||
Msg.STR["sel_tl"],
|
|
||||||
Msg.STR["tl_first"],
|
|
||||||
)
|
|
||||||
|
|
||||||
def handle_connection_state(self, action: str, tunnel_name: str = None) -> None:
|
def handle_connection_state(self, action: str, tunnel_name: str = None) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
import logging
|
import logging
|
||||||
import gettext
|
import gettext
|
||||||
import locale
|
import locale
|
||||||
|
import tkinter as tk
|
||||||
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from subprocess import CompletedProcess, run
|
from subprocess import CompletedProcess, run
|
||||||
from typing import Dict, Any
|
from typing import Dict, Any
|
||||||
@ -57,18 +59,18 @@ class AppConfig:
|
|||||||
|
|
||||||
# Updates
|
# Updates
|
||||||
# 1 = 1. Year, 09 = Month of the Year, 2924 = Day and Year of the Year
|
# 1 = 1. Year, 09 = Month of the Year, 2924 = Day and Year of the Year
|
||||||
VERSION: str = "v. 2.06.0725"
|
VERSION: str = "v. 2.07.0225"
|
||||||
UPDATE_URL: str = "https://git.ilunix.de/api/v1/repos/punix/Wire-Py/releases"
|
UPDATE_URL: str = "https://git.ilunix.de/api/v1/repos/punix/Wire-Py/releases"
|
||||||
DOWNLOAD_URL: str = "https://git.ilunix.de/punix/Wire-Py/archive"
|
DOWNLOAD_URL: str = "https://git.ilunix.de/punix/Wire-Py/archive"
|
||||||
|
|
||||||
# UI configuration
|
# UI configuration
|
||||||
UI_CONFIG: Dict[str, Any] = {
|
UI_CONFIG: Dict[str, Any] = {
|
||||||
"window_title": "Wire-Py",
|
"window_title": "",
|
||||||
"window_title2": "LogViewer",
|
"window_title2": "LogViewer",
|
||||||
"window_size": (600, 383),
|
"window_size": (590, 450),
|
||||||
"font_family": "Ubuntu",
|
"font_family": "Ubuntu",
|
||||||
"font_size": 11,
|
"font_size": 11,
|
||||||
"resizable_window": (False, False),
|
"resizable_window": (True, True),
|
||||||
}
|
}
|
||||||
|
|
||||||
# System-dependent paths
|
# System-dependent paths
|
||||||
@ -79,20 +81,6 @@ class AppConfig:
|
|||||||
"pkey_path": "/usr/local/etc/ssl/pwgk.pem",
|
"pkey_path": "/usr/local/etc/ssl/pwgk.pem",
|
||||||
}
|
}
|
||||||
|
|
||||||
# Images and icons paths
|
|
||||||
IMAGE_PATHS: Dict[str, Path] = {
|
|
||||||
"icon_vpn": "/usr/share/icons/lx-icons/48/wg_vpn.png",
|
|
||||||
"icon_msg": "/usr/share/icons/lx-icons/48/wg_msg.png",
|
|
||||||
"icon_import": "/usr/share/icons/lx-icons/48/wg_import.png",
|
|
||||||
"icon_export": "/usr/share/icons/lx-icons/48/wg_export.png",
|
|
||||||
"icon_trash": "/usr/share/icons/lx-icons/48/wg_trash.png",
|
|
||||||
"icon_start": "/usr/share/icons/lx-icons/48/wg_vpn-start.png",
|
|
||||||
"icon_stop": "/usr/share/icons/lx-icons/48/wg_vpn-stop.png",
|
|
||||||
"icon_info": "/usr/share/icons/lx-icons/64/info.png",
|
|
||||||
"icon_error": "/usr/share/icons/lx-icons/64/error.png",
|
|
||||||
"icon_log": "/usr/share/icons/lx-icons/48/log.png",
|
|
||||||
}
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def setup_translations() -> gettext.gettext:
|
def setup_translations() -> gettext.gettext:
|
||||||
"""
|
"""
|
||||||
@ -170,6 +158,65 @@ class AppConfig:
|
|||||||
_ = AppConfig.setup_translations()
|
_ = AppConfig.setup_translations()
|
||||||
|
|
||||||
|
|
||||||
|
class Image:
|
||||||
|
def __init__(self):
|
||||||
|
self.images = {}
|
||||||
|
|
||||||
|
def load_image(self, image_key, fallback_paths=None) -> None | tk.PhotoImage:
|
||||||
|
"""Load PNG image using tk.PhotoImage with fallback options"""
|
||||||
|
if image_key in self.images:
|
||||||
|
return self.images[image_key]
|
||||||
|
|
||||||
|
# Define image paths based on key
|
||||||
|
image_paths = {
|
||||||
|
"icon_header": [
|
||||||
|
"/usr/share/icons/lx-icons/32/wg_vpn.png",
|
||||||
|
],
|
||||||
|
"icon_vpn": [
|
||||||
|
"/usr/share/icons/lx-icons/48/wg_vpn.png",
|
||||||
|
],
|
||||||
|
"icon_start": [
|
||||||
|
"/usr/share/icons/lx-icons/48/wg_vpn-start.png",
|
||||||
|
],
|
||||||
|
"icon_stop": [
|
||||||
|
"/usr/share/icons/lx-icons/48/wg_vpn-stop.png",
|
||||||
|
],
|
||||||
|
"icon_import": [
|
||||||
|
"/usr/share/icons/lx-icons/48/wg_import.png",
|
||||||
|
],
|
||||||
|
"icon_export": [
|
||||||
|
"/usr/share/icons/lx-icons/48/wg_export.png",
|
||||||
|
],
|
||||||
|
"icon_trash": [
|
||||||
|
"/usr/share/icons/lx-icons/48/wg_trash.png",
|
||||||
|
],
|
||||||
|
"update": [
|
||||||
|
"/usr/share/icons/lx-icons/16/settings.png",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get paths to try
|
||||||
|
paths_to_try = image_paths.get(image_key, [])
|
||||||
|
|
||||||
|
# Add fallback paths if provided
|
||||||
|
if fallback_paths:
|
||||||
|
paths_to_try.extend(fallback_paths)
|
||||||
|
|
||||||
|
# Try to load image from paths
|
||||||
|
for path in paths_to_try:
|
||||||
|
try:
|
||||||
|
if os.path.exists(path):
|
||||||
|
photo = tk.PhotoImage(file=path)
|
||||||
|
self.images[image_key] = photo
|
||||||
|
return photo
|
||||||
|
except tk.TclError as e:
|
||||||
|
print(f"{LocaleStrings.MSGP['fail_load_image']}{path}: {e}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Return None if no image found
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class Msg:
|
class Msg:
|
||||||
"""
|
"""
|
||||||
A utility class that provides centralized access to translated message strings.
|
A utility class that provides centralized access to translated message strings.
|
||||||
@ -193,6 +240,8 @@ class Msg:
|
|||||||
|
|
||||||
STR: Dict[str, str] = {
|
STR: Dict[str, str] = {
|
||||||
# Strings for messages
|
# Strings for messages
|
||||||
|
"header_left_bottom": _("Simple GUI for Wireguard"),
|
||||||
|
"header_right_top": _("Wireguard VPN Manager"),
|
||||||
"sel_tl": _("Select tunnel"),
|
"sel_tl": _("Select tunnel"),
|
||||||
"ren_err": _("Renaming not possible"),
|
"ren_err": _("Renaming not possible"),
|
||||||
"exp_succ": _("Export successful"),
|
"exp_succ": _("Export successful"),
|
||||||
|