29.06.2025 (show changelog)

This commit is contained in:
2025-07-02 12:40:08 +02:00
parent e824094556
commit 12904e843c
9 changed files with 357 additions and 70 deletions

View File

@ -2,6 +2,7 @@
import tkinter as tk
from tkinter import ttk
import os
import sys
import subprocess
import getpass
from datetime import datetime
@ -37,12 +38,12 @@ class InstallationManager:
"""Install or update project"""
project_info = self.app_manager.get_project_info(project_key)
if not project_info:
raise Exception(f"{LocaleStrings.MSG["unknow_project"]}{project_key}")
raise Exception(f"{LocaleStrings.MSG['unknow_project']}{project_key}")
self.update_progress(
f"{LocaleStrings.MSGI["start_install"]}{project_info['name']}..."
f"{LocaleStrings.MSGI['start_install']}{project_info['name']}..."
)
self.log(f"=== {LocaleStrings.MSGI["install"]}{project_info['name']} ===")
self.log(f"=== {LocaleStrings.MSGI['install']}{project_info['name']} ===")
try:
# Create installation script
@ -52,19 +53,19 @@ class InstallationManager:
self._execute_install_script(script_content)
self.update_progress(
f"{project_info["name"]}{LocaleStrings.MSGI["install_success"]}"
f"{project_info['name']}{LocaleStrings.MSGI['install_success']}"
)
self.log(
f"=== {project_info["name"]}{LocaleStrings.MSGI["install_success"]} ==="
f"=== {project_info['name']}{LocaleStrings.MSGI['install_success']} ==="
)
# Set success icon
self.update_icon("success")
except Exception as e:
self.log(f"ERROR: {LocaleStrings.MSGI["install_failed"]}{e}")
self.log(f"ERROR: {LocaleStrings.MSGI['install_failed']}{e}")
self.update_icon("error")
raise Exception(f"{LocaleStrings.MSGI["install_failed"]}{e}")
raise Exception(f"{LocaleStrings.MSGI['install_failed']}{e}")
def _create_install_script(self, project_key):
"""Create installation script based on project"""
@ -73,7 +74,7 @@ class InstallationManager:
elif project_key == "logviewer":
return self._create_logviewer_install_script()
else:
raise Exception(f"{LocaleStrings.MSGI["unknow_project"]}{project_key}")
raise Exception(f"{LocaleStrings.MSGI['unknow_project']}{project_key}")
def _create_wirepy_install_script(self):
detected_os = Detector.get_os()
@ -331,7 +332,7 @@ echo "LogViewer installation completed!"
# Make script executable
os.chmod(script_file.name, 0o755)
self.log(f"{LocaleStrings.MSGI["install_create"]}{script_file.name}")
self.log(f"{LocaleStrings.MSGI['install_create']}{script_file.name}")
# Execute with pkexec
result = subprocess.run(
@ -352,13 +353,13 @@ echo "LogViewer installation completed!"
if result.returncode != 0:
raise Exception(
f"{LocaleStrings.MSGI["install_script_failed"]}{result.stderr}"
f"{LocaleStrings.MSGI['install_script_failed']}{result.stderr}"
)
except subprocess.TimeoutExpired:
raise Exception(LocaleStrings.MSGI["install_timeout"])
except subprocess.CalledProcessError as e:
raise Exception(f"{LocaleStrings.MSGI["install_script_failed"]}{e}")
raise Exception(f"{LocaleStrings.MSGI['install_script_failed']}{e}")
def update_progress(self, message):
if self.progress_callback:
@ -383,17 +384,17 @@ class UninstallationManager:
"""Uninstall project"""
project_info = self.app_manager.get_project_info(project_key)
if not project_info:
raise Exception(f"{LocaleStrings.MSGO["unknow_project"]}{project_key}")
raise Exception(f"{LocaleStrings.MSGO['unknow_project']}{project_key}")
if not self.app_manager.is_installed(project_key):
raise Exception(
f"{project_info["name"]}{LocaleStrings.MSGO["not_installed"]}"
f"{project_info['name']}{LocaleStrings.MSGO['not_installed']}"
)
self.update_progress(
f"{LocaleStrings.MSGU["uninstall"]}{project_info['name']}..."
f"{LocaleStrings.MSGU['uninstall']}{project_info['name']}..."
)
self.log(f"=== {LocaleStrings.MSGU["uninstall"]}{project_info['name']} ===")
self.log(f"=== {LocaleStrings.MSGU['uninstall']}{project_info['name']} ===")
try:
# Create uninstallation script
@ -403,15 +404,15 @@ class UninstallationManager:
self._execute_uninstall_script(script_content)
self.update_progress(
f"{project_info['name']}{LocaleStrings.MSGU["uninstall_success"]}"
f"{project_info['name']}{LocaleStrings.MSGU['uninstall_success']}"
)
self.log(
f"=== {project_info['name']}{LocaleStrings.MSGU["uninstall_success"]} ==="
f"=== {project_info['name']}{LocaleStrings.MSGU['uninstall_success']} ==="
)
except Exception as e:
self.log(f"ERROR: {LocaleStrings.MSGU['uninstall_failed']}{e}")
raise Exception(f"{LocaleStrings.MSGU["uninstall_failed"]}{e}")
raise Exception(f"{LocaleStrings.MSGU['uninstall_failed']}{e}")
def _create_uninstall_script(self, project_key):
"""Create uninstallation script based on project"""
@ -420,7 +421,7 @@ class UninstallationManager:
elif project_key == "logviewer":
return self._create_logviewer_uninstall_script()
else:
raise Exception(f"{LocaleStrings.MSGO["unknow_project"]}{project_key}")
raise Exception(f"{LocaleStrings.MSGO['unknow_project']}{project_key}")
def _create_wirepy_uninstall_script(self):
detected_os = Detector.get_os()
@ -555,7 +556,7 @@ echo "LogViewer uninstallation completed!"
# Make script executable
os.chmod(script_file.name, 0o755)
self.log(f"{LocaleStrings.MSGU["uninstall_create"]}{script_file.name}")
self.log(f"{LocaleStrings.MSGU['uninstall_create']}{script_file.name}")
# Execute with pkexec
result = subprocess.run(
@ -576,13 +577,13 @@ echo "LogViewer uninstallation completed!"
if result.returncode != 0:
raise Exception(
f"{LocaleStrings.MSGU["uninstall_script_failed"]}{result.stderr}"
f"{LocaleStrings.MSGU['uninstall_script_failed']}{result.stderr}"
)
except subprocess.TimeoutExpired:
raise Exception(LocaleStrings.MSGU["uninstall_timeout"])
except subprocess.CalledProcessError as e:
raise Exception(f"{LocaleStrings.MSGU["uninstall_script_failed"]}{e}")
raise Exception(f"{LocaleStrings.MSGU['uninstall_script_failed']}{e}")
def update_progress(self, message):
if self.progress_callback:
@ -599,7 +600,7 @@ class DownloadManager:
"""Download and extract ZIP file"""
try:
if progress_callback:
progress_callback(f"{LocaleStrings.MSGO["download_from"]}{url}...")
progress_callback(f"{LocaleStrings.MSGO['download_from']}{url}...")
with tempfile.NamedTemporaryFile(suffix=".zip", delete=False) as tmp_file:
urllib.request.urlretrieve(url, tmp_file.name)
@ -615,7 +616,7 @@ class DownloadManager:
except Exception as e:
if progress_callback:
progress_callback(f"{LocaleStrings.MSGO["download_failed"]}{e}")
progress_callback(f"{LocaleStrings.MSGO['download_failed']}{e}")
return False
@ -738,7 +739,7 @@ class LXToolsGUI:
tk.Label(
text_frame,
text=f"v {LXToolsAppConfig.VERSION}{LocaleStrings.MSGO["head_string3"]}",
text=f"v {LXToolsAppConfig.VERSION}{LocaleStrings.MSGO['head_string3']}",
font=("Helvetica", 9),
fg="#bdc3c7",
bg="#2c3e50",
@ -750,7 +751,7 @@ class LXToolsGUI:
tk.Label(
right_side,
text=f"{LocaleStrings.MSGO["head_string2"]}{self.detected_os}",
text=f"{LocaleStrings.MSGO['head_string2']}{self.detected_os}",
font=("Helvetica", 11),
fg="#ecf0f1",
bg="#2c3e50",
@ -774,10 +775,21 @@ class LXToolsGUI:
def check_ready_status(self):
"""Check if system is ready for installation"""
# Checks:
polkit_ok = Detector.get_polkit()
networkmanager_ok = Detector.get_networkmanager()
internet_ok = NetworkChecker.check_internet_connection()
repo_ok = NetworkChecker.check_repository_access()
result = Detector.get_host_python_version()
if not polkit_ok:
self.update_header_status(
LocaleStrings.MSGO["polkit_check"], "#e74c3c"
) # Red
if not networkmanager_ok:
self.update_header_status(
LocaleStrings.MSGO["networkmanager_check"], "#e74c3c"
) # Red
if internet_ok and repo_ok and result is not None:
self.update_header_status(LocaleStrings.MSGO["ready"], "#1abc9c") # Green
elif not internet_ok:
@ -897,7 +909,7 @@ class LXToolsGUI:
# Status label
status_label = tk.Label(
status_frame,
text=f"{LocaleStrings.MSGC["checking"]}",
text=f"{LocaleStrings.MSGC['checking']}",
font=("Helvetica", 10),
bg=self.colors["card_bg"],
fg="#95a5a6",
@ -991,7 +1003,7 @@ class LXToolsGUI:
self._update_frame_children_bg(new_content, self.colors["selected_bg"])
project_info = self.app_manager.get_project_info(project_key)
self.log_message(f"{LocaleStrings.MSGL["selected_app"]}{project_info["name"]}")
self.log_message(f"{LocaleStrings.MSGL['selected_app']}{project_info['name']}")
def _create_log_tab(self):
"""Create log tab"""
@ -1037,12 +1049,12 @@ class LXToolsGUI:
self.log_message(
f"=== {LXToolsAppConfig.APP_NAME} v {LXToolsAppConfig.VERSION} ==="
)
self.log_message(f"{LocaleStrings.MSGL["work_dir"]}{LXToolsAppConfig.WORK_DIR}")
self.log_message(f"{LocaleStrings.MSGL['work_dir']}{LXToolsAppConfig.WORK_DIR}")
self.log_message(
f"{LocaleStrings.MSGL["icons_dir"]}{LXToolsAppConfig.ICONS_DIR}"
f"{LocaleStrings.MSGL['icons_dir']}{LXToolsAppConfig.ICONS_DIR}"
)
self.log_message(f"{LocaleStrings.MSGL["detected_os"]}{self.detected_os}")
self.log_message(f"{LocaleStrings.MSGO["ready"]}...")
self.log_message(f"{LocaleStrings.MSGL['detected_os']}{self.detected_os}")
self.log_message(f"{LocaleStrings.MSGO['ready']}...")
def _create_progress_section(self):
"""Create progress section with download icon"""
@ -1062,7 +1074,7 @@ class LXToolsGUI:
# Progress Text (right, expandable)
self.progress_label = tk.Label(
progress_container,
text=f"{LocaleStrings.MSGO["ready"]}...",
text=f"{LocaleStrings.MSGO['ready']}...",
font=("Helvetica", 10),
fg="blue",
anchor="w",
@ -1175,22 +1187,22 @@ class LXToolsGUI:
"""Refresh application status and version information"""
self.update_progress(LocaleStrings.MSGI["refresh_and_check"])
self._reset_download_icon()
self.log_message(f"=== {LocaleStrings.MSGB["refresh"]} ===")
self.log_message(f"=== {LocaleStrings.MSGB['refresh']} ===")
self.root.focus_set()
for project_key, project_info in self.app_manager.get_all_projects().items():
status_label = self.status_labels[project_key]
version_label = self.version_labels[project_key]
self.log_message(f"{LocaleStrings.MSGC["checking"]} {project_info['name']}")
self.log_message(f"{LocaleStrings.MSGC['checking']} {project_info['name']}")
if self.app_manager.is_installed(project_key):
installed_version = self.app_manager.get_installed_version(project_key)
status_label.config(
text=f"{LocaleStrings.MSGI["installed"]}({installed_version})",
text=f"{LocaleStrings.MSGI['installed']}({installed_version})",
fg="green",
)
self.log_message(
f"{project_info['name']}: {LocaleStrings.MSGI["installed"]}({installed_version})"
f"{project_info['name']}: {LocaleStrings.MSGI['installed']}({installed_version})"
)
# Get latest version from API
@ -1199,41 +1211,41 @@ class LXToolsGUI:
if latest_version != "Unknown":
if installed_version != f"v. {latest_version}":
version_label.config(
text=f"{LocaleStrings.MSGC["latest"]}(v. {latest_version}) {LocaleStrings.MSGC["update_available"]}",
text=f"{LocaleStrings.MSGC['latest']}(v. {latest_version}) {LocaleStrings.MSGC['update_available']}",
fg="orange",
)
self.log_message(
f"{project_info['name']}: {LocaleStrings.MSGC["update_available"]}(v. {latest_version})"
f"{project_info['name']}: {LocaleStrings.MSGC['update_available']}(v. {latest_version})"
)
else:
version_label.config(
text=f"{LocaleStrings.MSGC["latest"]}: (v. {latest_version}) {LocaleStrings.MSGC["up_to_date"]}",
text=f"{LocaleStrings.MSGC['latest']}: (v. {latest_version}) {LocaleStrings.MSGC['up_to_date']}",
fg="green",
)
self.log_message(
f"{project_info['name']}: {LocaleStrings.MSGC["up_to_date"]}",
f"{project_info['name']}: {LocaleStrings.MSGC['up_to_date']}",
)
else:
version_label.config(
text=LocaleStrings.MSGC["latest_unknown"], fg="gray"
)
self.log_message(
f"{project_info['name']}: {LocaleStrings.MSGC["could_not_check"]}"
f"{project_info['name']}: {LocaleStrings.MSGC['could_not_check']}"
)
except Exception as e:
version_label.config(
text=LocaleStrings.MSGC["check_last_failed"], fg="gray"
)
self.log_message(
f"{project_info['name']}: {LocaleStrings.MSGC["version_check_failed"]}: {e}"
f"{project_info['name']}: {LocaleStrings.MSGC['version_check_failed']}: {e}"
)
else:
status_label.config(
text=f"{LocaleStrings.MSGC["not_installed"]}", fg="red"
text=f"{LocaleStrings.MSGC['not_installed']}", fg="red"
)
self.log_message(
f"{project_info['name']}: {LocaleStrings.MSGC["not_installed"]}"
f"{project_info['name']}: {LocaleStrings.MSGC['not_installed']}"
)
# Still show latest available version
@ -1241,12 +1253,12 @@ class LXToolsGUI:
latest_version = self.app_manager.get_latest_version(project_key)
if latest_version != "Unknown":
version_label.config(
text=f"{project_info['name']} {LocaleStrings.MSGC["available"]}: v {latest_version}",
text=f"{project_info['name']} {LocaleStrings.MSGC['available']}: v {latest_version}",
fg="blue",
)
self.log_message(
f"{project_info['name']} {LocaleStrings.MSGC["available"]}: v {latest_version}"
f"{project_info['name']} {LocaleStrings.MSGC['available']}: v {latest_version}"
)
else:
version_label.config(
@ -1257,11 +1269,11 @@ class LXToolsGUI:
text=LocaleStrings.MSGC["available_check_unknown"], fg="gray"
)
self.log_message(
f" {project_info['name']}: {LocaleStrings.MSGC["version_check_failed"]}: {e}"
f" {project_info['name']}: {LocaleStrings.MSGC['version_check_failed']}: {e}"
)
self.update_progress(LocaleStrings.MSGO["refresh2"])
self.log_message(f"=== {LocaleStrings.MSGO["refresh2"]} ===")
self.log_message(f"=== {LocaleStrings.MSGO['refresh2']} ===")
self.check_ready_status()
def install_selected(self):
@ -1294,7 +1306,7 @@ class LXToolsGUI:
self.update_download_icon("success")
MessageDialog(
"info",
f"{project_info["name"]} {LocaleStrings.MSGM["has_success_update"]}",
f"{project_info['name']} {LocaleStrings.MSGM['has_success_update']}",
wraplength=400,
)
@ -1317,7 +1329,7 @@ class LXToolsGUI:
if not self.app_manager.is_installed(self.selected_project):
MessageDialog(
"error", f"{project_info["name"]} {LocaleStrings.MSGO["not_installed"]}"
"error", f"{project_info['name']} {LocaleStrings.MSGO['not_installed']}"
)
self.root.focus_set()
return
@ -1326,14 +1338,14 @@ class LXToolsGUI:
self.uninstallation_manager.uninstall_project(self.selected_project)
MessageDialog(
"info",
f"{project_info["name"]} {LocaleStrings.MSGU["uninstall_success"]}",
f"{project_info['name']} {LocaleStrings.MSGU['uninstall_success']}",
wraplength=400,
)
self.refresh_status()
self.root.focus_set()
except Exception as e:
MessageDialog("error", f"{LocaleStrings.MSGU["uninstall_failed"]}: {e}")
MessageDialog("error", f"{LocaleStrings.MSGU['uninstall_failed']}: {e}")
self.root.focus_set()
def update_progress(self, message):
@ -1341,7 +1353,7 @@ class LXToolsGUI:
if self.progress_label:
self.progress_label.config(text=message)
self.progress_label.update()
print(f"{LocaleStrings.MSGO["progress"]}: {message}")
print(f"{LocaleStrings.MSGO['progress']}: {message}")
def log_message(self, message):
"""Add message to log"""
@ -1368,16 +1380,17 @@ class LXToolsGUI:
def main():
"""Main function to start the application"""
print(f"=== {LXToolsAppConfig.APP_NAME} v {LXToolsAppConfig.VERSION} ===")
print(f"{LocaleStrings.MSGL["working_dir"]}{os.getcwd()}")
print(f"{LocaleStrings.MSGL['working_dir']}{os.getcwd()}")
try:
LxTools.sigi(LXToolsAppConfig.TEMP_DIR)
# Create and run the GUI
app = LXToolsGUI()
app.run()
except KeyboardInterrupt:
print(LocaleStrings.MSGL["user_interrupt"])
except Exception as e:
print(f"{LocaleStrings.MSGL["fatal_error"]}: {e}")
print(f"{LocaleStrings.MSGL['fatal_error']}: {e}")
try:
MessageDialog("error", f"{LocaleStrings.MSGL['fatal_app_error']}: {e}")
@ -1387,3 +1400,6 @@ def main():
if __name__ == "__main__":
main()
LxTools.remove_lxtools_files()
LxTools.clean_files(LXToolsAppConfig.TEMP_DIR)
sys.exit(0)