diff --git a/.github/workflows/generate-linux-packages.yml b/.github/workflows/generate-linux-packages.yml new file mode 100644 index 00000000..bd5ba3cc --- /dev/null +++ b/.github/workflows/generate-linux-packages.yml @@ -0,0 +1,51 @@ +name: Generate Linux Packages + +on: + release: + types: [ published ] + +permissions: + contents: write + +jobs: + generate-windows-installer: + name: Generate Linux Packages + runs-on: ubuntu-latest + + steps: + - name: Git Checkout ${{github.event.release.tag_name}} + uses: actions/checkout@v6 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: '3.14' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install -r requirements.txt + + - name: Run PyInstaller to create binaries + run: | + pyinstaller --noconfirm turing-system-monitor.spec + echo "${{github.event.release.tag_name}}" > ./dist/turing-system-monitor/version.txt + ln -s configure ./dist/turing-system-monitor/turing-smart-screen + + - name: Create archive from generated binaries + run: | + rm -rf "./dist/turing-system-monitor/res/themes/--Theme examples" + tar -czvf "turing-system-monitor-${{github.event.release.tag_name}}-linux.tar.gz" -C "./dist/turing-system-monitor/" . + + - name: '📦 Archive Linux binaries' + uses: actions/upload-artifact@v7 + with: + name: turing-system-monitor-${{github.event.release.tag_name}}-linux + path: turing-system-monitor-${{github.event.release.tag_name}}-linux.tar.gz + if-no-files-found: error + + - name: '📩 Publish Linux binaries to Release' + run: | + gh release upload ${{github.event.release.tag_name}} turing-system-monitor-${{github.event.release.tag_name}}-linux.tar.gz + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/generate-windows-packages-debug.yml b/.github/workflows/generate-windows-packages-debug.yml index 80b2b33b..ba515f8f 100644 --- a/.github/workflows/generate-windows-packages-debug.yml +++ b/.github/workflows/generate-windows-packages-debug.yml @@ -44,30 +44,30 @@ jobs: - name: Create portable zip archive from generated binaries run: | Remove-Item -r ".\dist\turing-system-monitor\res\themes\--Theme examples\" - 7z a -tzip turing-system-monitor-${{github.event.release.tag_name}}-portable-debug.zip ".\dist\turing-system-monitor" + 7z a -tzip turing-system-monitor-${{github.event.release.tag_name}}-debug-portable-windows.zip ".\dist\turing-system-monitor" - name: '📦 Archive Windows installer' uses: actions/upload-artifact@v7 with: - name: turing-system-monitor-${{github.event.release.tag_name}}-debug - path: tools\windows-installer\Output\turing-system-monitor-${{github.event.release.tag_name}}-debug.exe + name: turing-system-monitor-${{github.event.release.tag_name}}-debug-windows + path: tools\windows-installer\Output\turing-system-monitor-${{github.event.release.tag_name}}-debug-windows.exe if-no-files-found: error - name: '📦 Archive Windows portable archive' uses: actions/upload-artifact@v7 with: - name: turing-system-monitor-${{github.event.release.tag_name}}-portable-debug - path: turing-system-monitor-${{github.event.release.tag_name}}-portable-debug.zip + name: turing-system-monitor-${{github.event.release.tag_name}}-debug-portable-windows + path: turing-system-monitor-${{github.event.release.tag_name}}-debug-portable-windows.zip if-no-files-found: error - name: '📩 Publish Windows installer to Release' run: | - gh release upload ${{github.event.release.tag_name}} tools\windows-installer\Output\turing-system-monitor-${{github.event.release.tag_name}}-debug.exe + gh release upload ${{github.event.release.tag_name}} tools\windows-installer\Output\turing-system-monitor-${{github.event.release.tag_name}}-debug-windows.exe env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: '📩 Publish Windows portable zip to Release' run: | - gh release upload ${{github.event.release.tag_name}} turing-system-monitor-${{github.event.release.tag_name}}-portable-debug.zip + gh release upload ${{github.event.release.tag_name}} turing-system-monitor-${{github.event.release.tag_name}}-debug-portable-windows.zip env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/generate-windows-packages.yml b/.github/workflows/generate-windows-packages.yml index b38c7417..fac6d446 100644 --- a/.github/workflows/generate-windows-packages.yml +++ b/.github/workflows/generate-windows-packages.yml @@ -44,30 +44,30 @@ jobs: - name: Create portable zip archive from generated binaries run: | Remove-Item -r ".\dist\turing-system-monitor\res\themes\--Theme examples\" - 7z a -tzip turing-system-monitor-${{github.event.release.tag_name}}-portable.zip ".\dist\turing-system-monitor" + 7z a -tzip turing-system-monitor-${{github.event.release.tag_name}}-portable-windows.zip ".\dist\turing-system-monitor" - name: '📦 Archive Windows installer' uses: actions/upload-artifact@v7 with: - name: turing-system-monitor-${{github.event.release.tag_name}} - path: tools\windows-installer\Output\turing-system-monitor-${{github.event.release.tag_name}}.exe + name: turing-system-monitor-${{github.event.release.tag_name}}-windows + path: tools\windows-installer\Output\turing-system-monitor-${{github.event.release.tag_name}}-windows.exe if-no-files-found: error - name: '📦 Archive Windows portable archive' uses: actions/upload-artifact@v7 with: - name: turing-system-monitor-${{github.event.release.tag_name}}-portable - path: turing-system-monitor-${{github.event.release.tag_name}}-portable.zip + name: turing-system-monitor-${{github.event.release.tag_name}}-portable-windows + path: turing-system-monitor-${{github.event.release.tag_name}}-portable-windows.zip if-no-files-found: error - name: '📩 Publish Windows installer to Release' run: | - gh release upload ${{github.event.release.tag_name}} tools\windows-installer\Output\turing-system-monitor-${{github.event.release.tag_name}}.exe + gh release upload ${{github.event.release.tag_name}} tools\windows-installer\Output\turing-system-monitor-${{github.event.release.tag_name}}-windows.exe env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: '📩 Publish Windows portable zip to Release' run: | - gh release upload ${{github.event.release.tag_name}} turing-system-monitor-${{github.event.release.tag_name}}-portable.zip + gh release upload ${{github.event.release.tag_name}} turing-system-monitor-${{github.event.release.tag_name}}-portable-windows.zip env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index df5d54cf..242a90ed 100644 --- a/.gitignore +++ b/.gitignore @@ -140,4 +140,5 @@ dmypy.json screencap.png tmp +version.txt external/LibreHardwareMonitor/LibreHardwareMonitorLib.sys diff --git a/configure.py b/configure.py index 565be5ce..9d799969 100755 --- a/configure.py +++ b/configure.py @@ -163,8 +163,10 @@ MAIN_DIRECTORY = Path(__file__).resolve().parent THEMES_DIR = MAIN_DIRECTORY / "res/themes" +VERSION_FILE = MAIN_DIRECTORY / "version.txt" circular_mask = Image.open(MAIN_DIRECTORY / "res/backgrounds/circular-mask.png") +DISABLED_COLOR = "#C0C0C0" def get_theme_data(name: str): @@ -323,6 +325,17 @@ def __init__(self): "Fans missing from the list? Install lm-sensors package\n" "and run 'sudo sensors-detect' command, then reboot.") + try: + version = open(VERSION_FILE).readline() + except: + try: + version = subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']).decode('utf-8') + except: + version = "0.0.0" + + version_label = ttk.Label(self.window, text=version, foreground=DISABLED_COLOR) + version_label.place(x=5, y=550) + self.weather_ping_btn = ttk.Button(self.window, text="Weather & ping", command=lambda: self.on_weatherping_click()) self.weather_ping_btn.place(x=80, y=520, height=50, width=130) @@ -510,13 +523,6 @@ def on_weatherping_click(self): self.more_config_window.show() def on_open_theme_folder_click(self): - # path = f'"{MAIN_DIRECTORY}res/themes"' - # if platform.system() == "Windows": - # os.startfile(path) - # elif platform.system() == "Darwin": - # subprocess.Popen(["open", path]) - # else: - # subprocess.Popen(["xdg-open", path]) path = MAIN_DIRECTORY / "res/themes" if platform.system() == "Windows": @@ -527,24 +533,35 @@ def on_open_theme_folder_click(self): subprocess.Popen(["xdg-open", str(path)]) def on_theme_editor_click(self): - theme_editor = next(MAIN_DIRECTORY.glob("theme-editor.*")) - - if platform.system() == "Windows": - subprocess.Popen([str(theme_editor), self.theme_cb.get()], shell=True) - else: - subprocess.Popen([str(theme_editor), self.theme_cb.get()]) + try: + # Load Python file with local python interpreter (useful for venvs) + theme_editor = next(MAIN_DIRECTORY.glob("theme-editor.py")) + subprocess.Popen([sys.executable, str(theme_editor), self.theme_cb.get()]) + except: + # Load binary (for releases) or Python file with system interpreter + theme_editor = next(MAIN_DIRECTORY.glob("theme-editor*")) + if platform.system() == "Windows": + subprocess.Popen([str(theme_editor), self.theme_cb.get()], shell=True) + else: + subprocess.Popen([str(theme_editor), self.theme_cb.get()]) def on_save_click(self): self.save_config_values() def on_saverun_click(self): self.save_config_values() - main_file = next(MAIN_DIRECTORY.glob("main.*")) - if platform.system() == "Windows": - subprocess.Popen([str(main_file)], shell=True) - else: - subprocess.Popen([str(main_file)]) + try: + # Load Python file with local python interpreter (useful for venvs) + main_file = next(MAIN_DIRECTORY.glob("main.py")) + subprocess.Popen([sys.executable, str(main_file)]) + except: + # Load binary (for releases) or Python file with system interpreter + main_file = next(MAIN_DIRECTORY.glob("main*")) + if platform.system() == "Windows": + subprocess.Popen([str(main_file)], shell=True) + else: + subprocess.Popen([str(main_file)]) self.window.destroy() @@ -556,10 +573,10 @@ def on_model_change(self, e=None): self.show_hide_brightness_warning() model = self.model_cb.get() if model == SIMULATED_MODEL: - self.com_cb.configure(state="disabled", foreground="#C0C0C0") - self.orient_cb.configure(state="disabled", foreground="#C0C0C0") + self.com_cb.configure(state="disabled", foreground=DISABLED_COLOR) + self.orient_cb.configure(state="disabled", foreground=DISABLED_COLOR) self.brightness_slider.configure(state="disabled") - self.brightness_val_label.configure(foreground="#C0C0C0") + self.brightness_val_label.configure(foreground=DISABLED_COLOR) else: self.com_cb.configure(state="readonly", foreground="#000") self.orient_cb.configure(state="readonly", foreground="#000") @@ -591,8 +608,8 @@ def on_size_change(self, e=None): def on_hwlib_change(self, e=None): hwlib = [k for k, v in hw_lib_map.items() if v == self.hwlib_cb.get()][0] if hwlib == "STUB" or hwlib == "STATIC": - self.eth_cb.configure(state="disabled", foreground="#C0C0C0") - self.wl_cb.configure(state="disabled", foreground="#C0C0C0") + self.eth_cb.configure(state="disabled", foreground=DISABLED_COLOR) + self.wl_cb.configure(state="disabled", foreground=DISABLED_COLOR) else: self.eth_cb.configure(state="readonly", foreground="#000") self.wl_cb.configure(state="readonly", foreground="#000") diff --git a/library/pythoncheck.py b/library/pythoncheck.py index ab51ab74..a820738e 100644 --- a/library/pythoncheck.py +++ b/library/pythoncheck.py @@ -24,19 +24,18 @@ # Oldest / newest version supported MIN_PYTHON = (3, 9) -MAX_PYTHON = (3, 14) # For Windows: max Python 3.13 until PythonNet support for 3.14 MAX_PYTHON_WINDOWS = (3, 13) +MAX_PYTHON_OTHERS = (3, 14) +MAX_PYTHON = MAX_PYTHON_WINDOWS if sys.platform == "win32" else MAX_PYTHON_OTHERS def check_python_version(): current_version = sys.version_info[:2] - platform = sys.platform - if current_version < MIN_PYTHON or (platform == "win32" and current_version > MAX_PYTHON_WINDOWS) or ( - platform != "win32" and current_version > MAX_PYTHON): + if current_version < MIN_PYTHON or current_version > MAX_PYTHON: print(f"[ERROR] Python {current_version[0]}.{current_version[1]} is not supported by this program. " - f"Python {MIN_PYTHON[0]}.{MIN_PYTHON[1]}-{MAX_PYTHON[0]}.{MAX_PYTHON[1]} required on platform {platform}.") + f"Python {MIN_PYTHON[0]}.{MIN_PYTHON[1]}-{MAX_PYTHON[0]}.{MAX_PYTHON[1]} required on platform {sys.platform}.") try: sys.exit(0) except: diff --git a/main.py b/main.py index 90e297a5..5e3f54ec 100755 --- a/main.py +++ b/main.py @@ -116,12 +116,18 @@ def on_signal_caught(signum, frame=None): def on_configure_tray(tray_icon, item): logger.info("Configure from tray icon") - configure_file = next(MAIN_DIRECTORY.glob("configure.*")) + try: + # Load Python file with local python interpreter (useful for venvs) + configure_file = next(MAIN_DIRECTORY.glob("configure.py")) + subprocess.Popen([sys.executable, str(configure_file)]) + except: + # Load binary (for releases) or Python file with system interpreter + configure_file = next(MAIN_DIRECTORY.glob("configure*")) + if platform.system() == "Windows": + subprocess.Popen([str(configure_file)], shell=True) + else: + subprocess.Popen([str(configure_file)]) - if platform.system() == "Windows": - subprocess.Popen([str(configure_file)], shell=True) - else: - subprocess.Popen([str(configure_file)]) clean_stop(tray_icon) def on_exit_tray(tray_icon, item): diff --git a/tools/windows-installer/turing-system-monitor.iss b/tools/windows-installer/turing-system-monitor.iss index 8ce31ccc..bdd4c82b 100644 --- a/tools/windows-installer/turing-system-monitor.iss +++ b/tools/windows-installer/turing-system-monitor.iss @@ -22,7 +22,7 @@ AppSupportURL={#MyAppURL}/wiki AppUpdatesURL={#MyAppURL}/releases DefaultDirName={autopf}\{#MyAppName} DefaultGroupName={#MyAppName} -OutputBaseFilename=turing-system-monitor-{#MyAppVersion} +OutputBaseFilename=turing-system-monitor-{#MyAppVersion}-windows AllowNoIcons=yes PrivilegesRequired=lowest Compression=lzma diff --git a/turing-system-monitor-debug.spec b/turing-system-monitor-debug.spec index 205f6baf..4e4a6dcc 100644 --- a/turing-system-monitor-debug.spec +++ b/turing-system-monitor-debug.spec @@ -7,7 +7,7 @@ configure_a = Analysis( pathex=[], binaries=[], datas=[('res', 'res'), ('config.yaml', '.'), ('external', 'external')], - hiddenimports=[], + hiddenimports=['PIL', 'PIL._imagingtk', 'PIL._tkinter_finder'], hookspath=[], hooksconfig={}, runtime_hooks=[], @@ -45,7 +45,7 @@ main_a = Analysis( pathex=[], binaries=[], datas=[('res', 'res'), ('config.yaml', '.'), ('external', 'external')], - hiddenimports=[], + hiddenimports=['PIL', 'PIL._imagingtk', 'PIL._tkinter_finder'], hookspath=[], hooksconfig={}, runtime_hooks=[], @@ -83,7 +83,7 @@ editor_a = Analysis( pathex=[], binaries=[], datas=[('res', 'res'), ('config.yaml', '.'), ('external', 'external')], - hiddenimports=[], + hiddenimports=['PIL', 'PIL._imagingtk', 'PIL._tkinter_finder'], hookspath=[], hooksconfig={}, runtime_hooks=[], diff --git a/turing-system-monitor.spec b/turing-system-monitor.spec index f1c1273d..1f1c3c11 100644 --- a/turing-system-monitor.spec +++ b/turing-system-monitor.spec @@ -7,7 +7,7 @@ configure_a = Analysis( pathex=[], binaries=[], datas=[('res', 'res'), ('config.yaml', '.'), ('external', 'external')], - hiddenimports=[], + hiddenimports=['PIL', 'PIL._imagingtk', 'PIL._tkinter_finder'], hookspath=[], hooksconfig={}, runtime_hooks=[], @@ -45,7 +45,7 @@ main_a = Analysis( pathex=[], binaries=[], datas=[('res', 'res'), ('config.yaml', '.'), ('external', 'external')], - hiddenimports=[], + hiddenimports=['PIL', 'PIL._imagingtk', 'PIL._tkinter_finder'], hookspath=[], hooksconfig={}, runtime_hooks=[], @@ -83,7 +83,7 @@ editor_a = Analysis( pathex=[], binaries=[], datas=[('res', 'res'), ('config.yaml', '.'), ('external', 'external')], - hiddenimports=[], + hiddenimports=['PIL', 'PIL._imagingtk', 'PIL._tkinter_finder'], hookspath=[], hooksconfig={}, runtime_hooks=[],