Browse Source

first commit

master
Matteo Benedetto 3 months ago
commit
1574f2853d
  1. 280
      .gitignore
  2. 60
      CHANGELOG.md
  3. 41
      LICENSE
  4. 124
      README.md
  5. 247
      README_EN.md
  6. 57
      config.example.json
  7. 207
      install.sh
  8. 501
      main.py
  9. 84
      pyproject.toml
  10. 26
      requirements.txt
  11. 35
      style.css

280
.gitignore vendored

@ -0,0 +1,280 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be added to the global gitignore or merged into this project gitignore.
# For PyCharm Community Edition, use 'PyCharm CE' instead of 'PyCharm'.
.idea/
# VSCode
.vscode/
*.code-workspace
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix
# macOS
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# Windows
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# Linux
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
# Project specific
# ComfyUI installations (if any get created locally)
ComfyUI/
comfy/
# Logs
*.log
logs/
# Configuration files that might contain sensitive info
config.json
*.ini
# Temporary files
*.tmp
*.temp
temp/
tmp/
# Archive files (shouldn't be committed)
*.zip
*.tar.gz
*.rar
*.7z
# Backup files
*.bak
*.backup
*~
# Editor swap files
*.swp
*.swo
*~
# GTK/GLib cache and temporary files
.cache/
gschemas.compiled
# Application specific temporary files
comfyui_*.pid
launcher_*.lock

60
CHANGELOG.md

@ -0,0 +1,60 @@
# Changelog
All notable changes to ComfyUI Launcher will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.0.0] - 2025-09-29
### Added
- Initial release of ComfyUI Launcher
- GTK4 based modern interface with libadwaita
- Full conda environment detection and management
- Automatic ComfyUI installation via comfy-cli
- Real-time process monitoring (checks every 3 seconds)
- Start/stop controls for ComfyUI
- Real-time log viewing with timestamps
- Status indicators with visual feedback
- Cross-platform support (Linux distributions)
- System dependency detection and installation guidance
- Desktop integration file
- Comprehensive documentation in English and Italian
- Automated installation script for Fedora and Debian-based systems
### Features
- **Environment Management**: Automatic detection of conda environments
- **Process Control**: Start, stop, and monitor ComfyUI processes
- **Real-time Monitoring**: Continuous status checking via port 8188 and process detection
- **Installation Assistant**: One-click installation of ComfyUI and dependencies
- **Log Viewer**: Real-time output display with monospace font
- **Modern UI**: GTK4 interface with proper dark/light theme support
- **Cross-distribution Support**: Works on Fedora, Ubuntu, Debian, and other Linux distributions
### System Requirements
- Python 3.9 or higher
- GTK4 and libadwaita
- Conda or Miniconda
- Cairo, GObject Introspection development libraries
### Known Issues
- Font fallback may not work properly on systems without monospace fonts
- Some older GTK themes may not display correctly with libadwaita
### Documentation
- Complete installation guide for Debian and Fedora
- Troubleshooting section for common issues
- Development setup instructions
- Contributing guidelines
### Files Added
- `main.py` - Main application code
- `requirements.txt` - Python dependencies
- `install.sh` - Automated installation script
- `README_EN.md` - English documentation
- `README.md` - Italian documentation
- `style.css` - Custom GTK styles
- `pyproject.toml` - Project configuration
- `.gitignore` - Git ignore rules
- `LICENSE` - MIT license
- `CHANGELOG.md` - This changelog

41
LICENSE

@ -0,0 +1,41 @@
MIT License
Copyright (c) 2025 ComfyUI Launcher Team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Copyright (c) 2025 [Il tuo nome]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

124
README.md

@ -0,0 +1,124 @@
# ComfyUI Launcher
Un launcher GTK4 moderno per ComfyUI con supporto completo per ambienti conda.
## Caratteristiche
- 🚀 **Gestione Ambienti Conda**: Selezione facile degli ambienti conda disponibili
- 🔧 **Installazione Automatica**: Installa ComfyUI e comfy-cli con un click
- 📊 **Monitoraggio in Tempo Reale**: Controlla continuamente se ComfyUI è in esecuzione
- 🎮 **Controlli Intuitivi**: Avvia e ferma ComfyUI facilmente
- 📝 **Log in Tempo Reale**: Visualizza l'output di ComfyUI direttamente nel launcher
- 🎨 **Interfaccia Moderna**: Basata su GTK4 e libadwaita
## Prerequisiti
- Python 3.9 o superiore
- conda o miniconda installato
- GTK4 e libadwaita
- Librerie di sviluppo (cairo-devel, gobject-introspection-devel, ecc.)
## Installazione Dipendenze Sistema
### Fedora/RHEL:
```bash
sudo dnf install cairo-devel gobject-introspection-devel gtk3-devel pkg-config python3-devel
```
### Ubuntu/Debian:
```bash
sudo apt install libcairo2-dev libgirepository1.0-dev libgtk-3-dev pkg-config python3-dev
```
## Installazione
1. Clona il repository:
```bash
git clone <repository-url>
cd gtk-app
```
2. Crea e attiva l'ambiente virtuale:
```bash
python3 -m venv .venv
source .venv/bin/activate
```
3. Installa le dipendenze Python:
```bash
pip install pygobject
```
## Utilizzo
1. Avvia il launcher:
```bash
python main.py
```
2. Seleziona un ambiente conda dalla lista dropdown
3. Se ComfyUI non è installato nell'ambiente, clicca "Installa ComfyUI"
4. Una volta installato, usa "Avvia ComfyUI" per lanciare ComfyUI
5. Il launcher monitorerà automaticamente lo stato di ComfyUI
## Funzionalità Dettagliate
### Gestione Ambienti Conda
- Lista automatica di tutti gli ambienti conda disponibili
- Supporto per l'ambiente base
- Pulsante di aggiornamento per ricaricare la lista
### Monitoraggio Stato
- Controllo ogni 3 secondi se ComfyUI è in esecuzione
- Indicatore visivo dello stato (icona e colore)
- Rilevamento tramite porta 8188 e processi attivi
### Controlli
- **Avvia ComfyUI**: Lancia ComfyUI nell'ambiente selezionato
- **Ferma ComfyUI**: Termina gracefully il processo ComfyUI
- **Installa ComfyUI**: Installa comfy-cli e ComfyUI nell'ambiente
### Log
- Output in tempo reale di ComfyUI
- Timestamp per ogni messaggio
- Font monospace per miglior leggibilità
## File di Configurazione
- `main.py`: Applicazione principale
- `style.css`: Stili personalizzati (opzionale)
- `comfyui-launcher.desktop`: File desktop per integrazione sistema
## Problemi Comuni
### Conda non trovato
Assicurati che conda sia nel PATH:
```bash
export PATH="$HOME/miniconda3/bin:$PATH"
```
### Errori di permessi
Su alcuni sistemi potrebbe essere necessario rendere eseguibile lo script:
```bash
chmod +x main.py
```
### ComfyUI non si avvia
- Verifica che l'ambiente conda abbia Python 3.9+
- Controlla che comfy-cli sia installato correttamente
- Verifica i log per eventuali errori specifici
## Contribuire
Contributi sono benvenuti! Per favore:
1. Fai un fork del repository
2. Crea un branch per la tua feature
3. Committa le modifiche
4. Apri una Pull Request
## Licenza
MIT License - vedi il file LICENSE per dettagli.

247
README_EN.md

@ -0,0 +1,247 @@
# ComfyUI Launcher
A modern GTK4 launcher for ComfyUI with full conda environment support.
![GTK4](https://img.shields.io/badge/GTK-4.0-blue)
![Python](https://img.shields.io/badge/Python-3.9+-green)
![License](https://img.shields.io/badge/License-MIT-yellow)
## Features
- 🚀 **Conda Environment Management**: Easy selection of available conda environments
- 🔧 **Automatic Installation**: Install ComfyUI and comfy-cli with one click
- 📊 **Real-time Monitoring**: Continuously monitors if ComfyUI is running
- 🎮 **Intuitive Controls**: Start and stop ComfyUI easily
- 📝 **Real-time Logs**: View ComfyUI output directly in the launcher
- 🎨 **Modern Interface**: Built with GTK4 and libadwaita
## Prerequisites
- Python 3.9 or higher
- conda or miniconda installed
- GTK4 and libadwaita
- Development libraries (cairo-devel, gobject-introspection-devel, etc.)
## System Dependencies Installation
### Fedora/RHEL/CentOS/Rocky Linux
```bash
# Install system dependencies
sudo dnf install cairo-devel gobject-introspection-devel gtk4-devel pkg-config python3-devel
# Install conda if not already installed
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh
```
### Debian/Ubuntu
```bash
# Update package list
sudo apt update
# Install system dependencies
sudo apt install libcairo2-dev libgirepository1.0-dev libgtk-4-dev pkg-config python3-dev python3-venv
# Install conda if not already installed
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh
```
## Installation
1. **Clone the repository:**
```bash
git clone <repository-url>
cd gtk-app
```
2. **Create and activate virtual environment:**
```bash
python3 -m venv .venv
source .venv/bin/activate
```
3. **Install Python dependencies:**
```bash
pip install -r requirements.txt
```
## Usage
### Quick Start
1. **Launch the application:**
```bash
python main.py
```
or use the provided script:
```bash
./run.sh
```
2. **Select a conda environment** from the dropdown list
3. **Install ComfyUI** (if not already installed) by clicking "Install ComfyUI"
4. **Start ComfyUI** by clicking "Start ComfyUI"
5. The launcher will **automatically monitor** ComfyUI status
### Detailed Workflow
1. **Environment Selection**
- The launcher automatically detects all available conda environments
- Select your preferred environment from the dropdown
- Click "Refresh Environment List" to reload environments
2. **ComfyUI Installation**
- If ComfyUI is not installed in the selected environment, click "Install ComfyUI"
- This will install both `comfy-cli` and ComfyUI automatically
- Installation progress is shown in the log window
3. **Running ComfyUI**
- Click "Start ComfyUI" to launch ComfyUI in the selected environment
- Real-time output appears in the log window
- The status indicator shows when ComfyUI is running
4. **Monitoring**
- The launcher checks every 3 seconds if ComfyUI is running
- Status is indicated by both text and visual indicators
- Automatic detection works even if ComfyUI was started outside the launcher
## Features Detail
### Environment Management
- Automatic detection of all conda environments
- Support for conda base environment
- Refresh button to reload environment list
- Clear indication of selected environment
### Status Monitoring
- Checks every 3 seconds if ComfyUI is running
- Visual status indicator (icon and color)
- Detection via port 8188 and active processes
- Works even with externally started ComfyUI instances
### Controls
- **Start ComfyUI**: Launch ComfyUI in selected environment
- **Stop ComfyUI**: Gracefully terminate ComfyUI process
- **Install ComfyUI**: Install comfy-cli and ComfyUI in environment
- **Refresh Environments**: Reload conda environment list
### Logging
- Real-time output from ComfyUI
- Timestamp for each message
- Monospace font for better readability
- Automatic scrolling to latest messages
## File Structure
```
gtk-app/
├── main.py # Main application
├── requirements.txt # Python dependencies
├── style.css # Custom styles (optional)
├── comfyui-launcher.desktop # Desktop integration file
├── run.sh # Launch script
├── README.md # This file
├── .gitignore # Git ignore rules
└── .venv/ # Virtual environment (created after setup)
```
## Troubleshooting
### Conda not found
Make sure conda is in your PATH:
```bash
export PATH="$HOME/miniconda3/bin:$PATH"
# Add to ~/.bashrc or ~/.zshrc for persistence
echo 'export PATH="$HOME/miniconda3/bin:$PATH"' >> ~/.bashrc
```
### Permission errors
Make the script executable:
```bash
chmod +x main.py
chmod +x run.sh
```
### ComfyUI won't start
- Verify the conda environment has Python 3.9+
- Check that comfy-cli is properly installed
- Review logs for specific error messages
- Ensure sufficient disk space and memory
### GTK/PyGObject errors
Make sure all system dependencies are installed:
```bash
# Fedora/RHEL
sudo dnf install gtk4-devel python3-gobject
# Debian/Ubuntu
sudo apt install libgtk-4-dev python3-gi
```
### Missing fonts
The launcher uses monospace fonts for logs. If fonts appear wrong:
```bash
# Install additional fonts (optional)
sudo dnf install jetbrains-mono-fonts # Fedora
sudo apt install fonts-jetbrains-mono # Ubuntu
```
## Development
### Setting up development environment
1. Fork the repository
2. Clone your fork
3. Install development dependencies:
```bash
pip install -r requirements.txt
```
4. Make your changes
5. Test thoroughly
6. Submit a pull request
### Code Style
- Follow PEP 8 for Python code
- Use meaningful variable names
- Add comments for complex logic
- Keep functions focused and small
## Contributing
Contributions are welcome! Please:
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests if applicable
5. Update documentation
6. Submit a pull request
## License
MIT License - see the LICENSE file for details.
## Acknowledgments
- [ComfyUI](https://github.com/comfyanonymous/ComfyUI) - The amazing stable diffusion GUI
- [comfy-cli](https://github.com/Comfy-Org/comfy-cli) - Command line tool for ComfyUI
- [GTK](https://gtk.org/) - The GUI toolkit
- [PyGObject](https://pygobject.readthedocs.io/) - Python bindings for GTK
## Support
If you encounter issues:
1. Check the troubleshooting section above
2. Search existing GitHub issues
3. Create a new issue with:
- Your operating system and version
- Python version
- Complete error messages
- Steps to reproduce the problem

57
config.example.json

@ -0,0 +1,57 @@
{
"_comment": "ComfyUI Launcher Configuration Template",
"_instructions": "Copy this file to ~/.config/comfyui-launcher/config.json to customize settings",
"launcher": {
"window": {
"width": 900,
"height": 700,
"remember_size": true,
"remember_position": true
},
"monitoring": {
"check_interval_seconds": 3,
"port_to_check": 8188,
"process_patterns": [
"comfy.*launch",
"python.*main.py.*comfyui"
]
},
"logging": {
"max_log_lines": 1000,
"auto_scroll": true,
"timestamp_format": "%H:%M:%S",
"font_family": "JetBrains Mono, Fira Code, Source Code Pro, monospace",
"font_size": "10pt"
},
"conda": {
"auto_refresh_on_startup": true,
"preferred_environments": [],
"exclude_environments": []
},
"comfyui": {
"default_args": [],
"auto_start_browser": false,
"startup_timeout_seconds": 60,
"shutdown_timeout_seconds": 10
}
},
"paths": {
"conda_executable": "conda",
"comfy_executable": "comfy",
"default_comfyui_directory": "~/comfy/ComfyUI"
},
"ui": {
"theme": "auto",
"use_dark_theme": null,
"accent_color": "#3584e4",
"show_tooltips": true,
"animations_enabled": true
},
"advanced": {
"debug_mode": false,
"verbose_logging": false,
"check_for_updates": true,
"telemetry_enabled": false
}
}

207
install.sh

@ -0,0 +1,207 @@
#!/bin/bash
# ComfyUI Launcher Installation Script
# This script automates the installation process for different Linux distributions
set -e # Exit on any error
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Function to print colored output
print_status() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Detect Linux distribution
detect_distro() {
if [ -f /etc/os-release ]; then
. /etc/os-release
DISTRO=$ID
VERSION=$VERSION_ID
else
print_error "Cannot detect Linux distribution"
exit 1
fi
}
# Install system dependencies based on distribution
install_system_deps() {
print_status "Installing system dependencies for $DISTRO..."
case $DISTRO in
"fedora"|"rhel"|"centos"|"rocky")
sudo dnf install -y cairo-devel gobject-introspection-devel gtk4-devel pkg-config python3-devel python3-pip
;;
"ubuntu"|"debian")
sudo apt update
sudo apt install -y libcairo2-dev libgirepository1.0-dev libgtk-4-dev pkg-config python3-dev python3-pip python3-venv
;;
"arch"|"manjaro")
sudo pacman -S --needed cairo gobject-introspection gtk4 pkgconf python python-pip
;;
*)
print_warning "Unsupported distribution: $DISTRO"
print_warning "Please install the following packages manually:"
print_warning "- Cairo development libraries"
print_warning "- GObject Introspection development libraries"
print_warning "- GTK4 development libraries"
print_warning "- pkg-config"
print_warning "- Python 3.9+ development headers"
;;
esac
}
# Check if conda is installed
check_conda() {
if command -v conda &> /dev/null; then
print_success "Conda found: $(conda --version)"
return 0
else
print_warning "Conda not found"
return 1
fi
}
# Install conda if not present
install_conda() {
print_status "Installing Miniconda..."
# Detect architecture
ARCH=$(uname -m)
if [ "$ARCH" = "x86_64" ]; then
CONDA_URL="https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh"
elif [ "$ARCH" = "aarch64" ]; then
CONDA_URL="https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-aarch64.sh"
else
print_error "Unsupported architecture: $ARCH"
exit 1
fi
# Download and install conda
wget "$CONDA_URL" -O miniconda.sh
bash miniconda.sh -b -p "$HOME/miniconda3"
rm miniconda.sh
# Add conda to PATH
echo 'export PATH="$HOME/miniconda3/bin:$PATH"' >> ~/.bashrc
export PATH="$HOME/miniconda3/bin:$PATH"
# Initialize conda
conda init bash
print_success "Miniconda installed successfully"
print_warning "Please restart your terminal or run: source ~/.bashrc"
}
# Setup Python virtual environment
setup_venv() {
print_status "Setting up Python virtual environment..."
if [ ! -d ".venv" ]; then
python3 -m venv .venv
print_success "Virtual environment created"
else
print_status "Virtual environment already exists"
fi
# Activate virtual environment
source .venv/bin/activate
# Upgrade pip
pip install --upgrade pip
# Install requirements
if [ -f "requirements.txt" ]; then
print_status "Installing Python dependencies..."
pip install -r requirements.txt
print_success "Python dependencies installed"
else
print_warning "requirements.txt not found, installing basic dependencies..."
pip install PyGObject
fi
}
# Make scripts executable
make_executable() {
print_status "Making scripts executable..."
chmod +x main.py 2>/dev/null || true
chmod +x run.sh 2>/dev/null || true
print_success "Scripts are now executable"
}
# Create desktop entry (optional)
create_desktop_entry() {
if [ -f "comfyui-launcher.desktop" ]; then
read -p "Install desktop entry? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
DESKTOP_FILE="$HOME/.local/share/applications/comfyui-launcher.desktop"
mkdir -p "$(dirname "$DESKTOP_FILE")"
# Update paths in desktop file
CURRENT_DIR=$(pwd)
sed "s|/home/enne2/Development/gtk-app|$CURRENT_DIR|g" comfyui-launcher.desktop > "$DESKTOP_FILE"
print_success "Desktop entry installed to $DESKTOP_FILE"
fi
fi
}
# Main installation function
main() {
print_status "ComfyUI Launcher Installation Script"
print_status "======================================"
# Detect distribution
detect_distro
print_status "Detected distribution: $DISTRO $VERSION"
# Install system dependencies
install_system_deps
# Check for conda
if ! check_conda; then
read -p "Install Miniconda? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
install_conda
else
print_warning "Conda not installed. You'll need to install it manually for full functionality."
fi
fi
# Setup Python environment
setup_venv
# Make scripts executable
make_executable
# Optional desktop entry
create_desktop_entry
print_success "Installation completed!"
print_status "To run the launcher:"
print_status " ./run.sh"
print_status "or:"
print_status " source .venv/bin/activate && python main.py"
}
# Run main function
main "$@"

501
main.py

@ -0,0 +1,501 @@
#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw, Gio, GLib
import sys
import subprocess
import json
import os
import threading
import time
import re
class ComfyUILauncher(Gtk.ApplicationWindow):
def __init__(self, **kwargs):
super().__init__(**kwargs)
# Configurazione finestra principale
self.set_title("ComfyUI Launcher")
self.set_default_size(900, 700)
# Variabili di stato
self.comfyui_process = None
self.is_running = False
self.selected_conda_env = None
self.conda_envs = []
self.status_check_timeout = None
# Crea il layout principale
self.setup_ui()
# Inizializza il controllo degli ambienti conda
self.load_conda_environments()
# Avvia il monitoraggio dello stato
self.start_status_monitoring()
def setup_ui(self):
# Header bar
header = Gtk.HeaderBar()
header.set_title_widget(Gtk.Label(label="ComfyUI Launcher"))
self.set_titlebar(header)
# Menu button
menu_button = Gtk.MenuButton()
menu_button.set_icon_name("open-menu-symbolic")
header.pack_end(menu_button)
# Main content area
main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12)
main_box.set_margin_top(12)
main_box.set_margin_bottom(12)
main_box.set_margin_start(12)
main_box.set_margin_end(12)
# Title
title_label = Gtk.Label()
title_label.set_markup("<span size='x-large'><b>ComfyUI Launcher</b></span>")
title_label.set_margin_bottom(12)
main_box.append(title_label)
# Status section
status_frame = Gtk.Frame()
status_frame.set_label("Stato ComfyUI")
status_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=12)
status_box.set_margin_top(12)
status_box.set_margin_bottom(12)
status_box.set_margin_start(12)
status_box.set_margin_end(12)
self.status_indicator = Gtk.Image()
self.status_indicator.set_from_icon_name("media-playback-stop-symbolic")
self.status_indicator.set_icon_size(Gtk.IconSize.LARGE)
status_box.append(self.status_indicator)
self.status_label = Gtk.Label(label="ComfyUI non in esecuzione")
self.status_label.set_hexpand(True)
self.status_label.set_halign(Gtk.Align.START)
status_box.append(self.status_label)
status_frame.set_child(status_box)
main_box.append(status_frame)
# Environment selection
env_frame = Gtk.Frame()
env_frame.set_label("Selezione Ambiente Conda")
env_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
env_box.set_margin_top(12)
env_box.set_margin_bottom(12)
env_box.set_margin_start(12)
env_box.set_margin_end(12)
# Dropdown per ambienti conda
self.env_dropdown = Gtk.DropDown()
self.env_dropdown.set_enable_search(True)
self.env_dropdown.connect("notify::selected-item", self.on_env_selected)
env_box.append(self.env_dropdown)
# Refresh button
refresh_button = Gtk.Button(label="Aggiorna Lista Ambienti")
refresh_button.connect("clicked", self.on_refresh_envs)
env_box.append(refresh_button)
env_frame.set_child(env_box)
main_box.append(env_frame)
# Control buttons
control_frame = Gtk.Frame()
control_frame.set_label("Controlli")
control_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=12)
control_box.set_margin_top(12)
control_box.set_margin_bottom(12)
control_box.set_margin_start(12)
control_box.set_margin_end(12)
control_box.set_homogeneous(True)
self.start_button = Gtk.Button(label="Avvia ComfyUI")
self.start_button.add_css_class("suggested-action")
self.start_button.connect("clicked", self.on_start_comfyui)
self.start_button.set_sensitive(False)
control_box.append(self.start_button)
self.stop_button = Gtk.Button(label="Ferma ComfyUI")
self.stop_button.add_css_class("destructive-action")
self.stop_button.connect("clicked", self.on_stop_comfyui)
self.stop_button.set_sensitive(False)
control_box.append(self.stop_button)
self.install_button = Gtk.Button(label="Installa ComfyUI")
self.install_button.connect("clicked", self.on_install_comfyui)
control_box.append(self.install_button)
control_frame.set_child(control_box)
main_box.append(control_frame)
# Log section
log_frame = Gtk.Frame()
log_frame.set_label("Log")
log_frame.set_vexpand(True)
scrolled = Gtk.ScrolledWindow()
scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
scrolled.set_vexpand(True)
self.log_view = Gtk.TextView()
self.log_view.set_editable(False)
self.log_view.set_monospace(True)
self.log_buffer = self.log_view.get_buffer()
scrolled.set_child(self.log_view)
log_frame.set_child(scrolled)
main_box.append(log_frame)
self.set_child(main_box)
# Setup menu
self.setup_menu(menu_button)
def setup_menu(self, menu_button):
menu = Gio.Menu()
menu.append("Apri Cartella ComfyUI", "app.open_folder")
menu.append("About", "app.about")
menu.append("Quit", "app.quit")
menu_button.set_menu_model(menu)
def log_message(self, message):
"""Aggiunge un messaggio al log"""
def update_log():
current_text = self.log_buffer.get_text(
self.log_buffer.get_start_iter(),
self.log_buffer.get_end_iter(),
False
)
timestamp = time.strftime("%H:%M:%S")
new_text = f"{current_text}[{timestamp}] {message}\n" if current_text else f"[{timestamp}] {message}\n"
self.log_buffer.set_text(new_text)
# Scorri alla fine
mark = self.log_buffer.get_insert()
self.log_view.scroll_mark_onscreen(mark)
GLib.idle_add(update_log)
def load_conda_environments(self):
"""Carica la lista degli ambienti conda disponibili"""
def load_envs():
try:
# Prova a ottenere la lista degli ambienti conda
result = subprocess.run(['conda', 'env', 'list', '--json'],
capture_output=True, text=True, timeout=30)
if result.returncode == 0:
env_data = json.loads(result.stdout)
envs = []
for env_path in env_data['envs']:
env_name = os.path.basename(env_path)
if env_name == env_path: # È il path base, usa 'base'
env_name = 'base'
envs.append((env_name, env_path))
def update_ui():
self.conda_envs = envs
string_list = Gtk.StringList()
for name, path in envs:
string_list.append(f"{name} ({path})")
self.env_dropdown.set_model(string_list)
if envs:
self.env_dropdown.set_selected(0)
self.log_message(f"Trovati {len(envs)} ambienti conda")
GLib.idle_add(update_ui)
else:
GLib.idle_add(lambda: self.log_message(f"Errore nel caricare ambienti conda: {result.stderr}"))
except subprocess.TimeoutExpired:
GLib.idle_add(lambda: self.log_message("Timeout nel caricamento ambienti conda"))
except FileNotFoundError:
GLib.idle_add(lambda: self.log_message("Conda non trovato. Assicurati che conda sia installato e nel PATH"))
except Exception as e:
GLib.idle_add(lambda: self.log_message(f"Errore imprevisto: {str(e)}"))
# Esegui in un thread separato per non bloccare l'UI
threading.Thread(target=load_envs, daemon=True).start()
def on_env_selected(self, dropdown, param):
"""Gestisce la selezione di un ambiente conda"""
selected_idx = dropdown.get_selected()
if selected_idx != Gtk.INVALID_LIST_POSITION and self.conda_envs:
env_name, env_path = self.conda_envs[selected_idx]
self.selected_conda_env = (env_name, env_path)
self.log_message(f"Selezionato ambiente: {env_name}")
self.update_button_states()
def on_refresh_envs(self, button):
"""Aggiorna la lista degli ambienti conda"""
self.log_message("Aggiornamento lista ambienti...")
self.load_conda_environments()
def update_button_states(self):
"""Aggiorna lo stato dei pulsanti in base allo stato corrente"""
has_env = self.selected_conda_env is not None
self.start_button.set_sensitive(has_env and not self.is_running)
self.stop_button.set_sensitive(self.is_running)
self.install_button.set_sensitive(has_env)
def check_comfyui_running(self):
"""Controlla se ComfyUI è in esecuzione"""
try:
# Controlla se il processo ComfyUI è ancora vivo
if self.comfyui_process and self.comfyui_process.poll() is None:
return True
# Controlla se c'è un processo ComfyUI in esecuzione (porta 8188)
try:
result = subprocess.run(['ss', '-tulpn'], capture_output=True, text=True, timeout=5)
if ':8188' in result.stdout:
return True
except:
# Fallback con netstat se ss non è disponibile
try:
result = subprocess.run(['netstat', '-tulpn'], capture_output=True, text=True, timeout=5)
if ':8188' in result.stdout:
return True
except:
pass
# Controlla processi con nome 'comfy' o 'python' che potrebbero essere ComfyUI
try:
result = subprocess.run(['pgrep', '-f', 'comfy.*launch'], capture_output=True, text=True, timeout=5)
if result.returncode == 0 and result.stdout.strip():
return True
except:
pass
return False
except Exception as e:
self.log_message(f"Errore nel controllo stato: {str(e)}")
return False
def update_status_ui(self):
"""Aggiorna l'interfaccia utente con lo stato corrente"""
if self.is_running:
self.status_indicator.set_from_icon_name("media-playback-start-symbolic")
self.status_indicator.add_css_class("success")
self.status_label.set_text("ComfyUI in esecuzione")
else:
self.status_indicator.set_from_icon_name("media-playback-stop-symbolic")
self.status_indicator.remove_css_class("success")
self.status_label.set_text("ComfyUI non in esecuzione")
self.update_button_states()
def start_status_monitoring(self):
"""Avvia il monitoraggio periodico dello stato"""
def monitor():
was_running = self.is_running
self.is_running = self.check_comfyui_running()
if was_running != self.is_running:
if self.is_running:
self.log_message("ComfyUI rilevato in esecuzione")
else:
self.log_message("ComfyUI non più in esecuzione")
GLib.idle_add(self.update_status_ui)
return True # Continua il monitoring
# Controlla ogni 3 secondi
self.status_check_timeout = GLib.timeout_add(3000, monitor)
def on_start_comfyui(self, button):
"""Avvia ComfyUI"""
if not self.selected_conda_env:
self.log_message("Nessun ambiente conda selezionato")
return
env_name, env_path = self.selected_conda_env
self.log_message(f"Avvio ComfyUI nell'ambiente {env_name}...")
def start_comfy():
try:
# Comando per attivare l'ambiente conda e avviare comfyui
if env_name == 'base':
cmd = ['conda', 'run', '-n', 'base', 'comfy', 'launch']
else:
cmd = ['conda', 'run', '-n', env_name, 'comfy', 'launch']
self.comfyui_process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1,
universal_newlines=True
)
GLib.idle_add(lambda: self.log_message("Processo ComfyUI avviato"))
# Leggi l'output in tempo reale
for line in iter(self.comfyui_process.stdout.readline, ''):
if line:
GLib.idle_add(lambda l=line.strip(): self.log_message(f"ComfyUI: {l}"))
except Exception as e:
GLib.idle_add(lambda: self.log_message(f"Errore nell'avvio: {str(e)}"))
threading.Thread(target=start_comfy, daemon=True).start()
def on_stop_comfyui(self, button):
"""Ferma ComfyUI"""
self.log_message("Fermando ComfyUI...")
if self.comfyui_process:
try:
self.comfyui_process.terminate()
# Aspetta un po' per la terminazione graceful
try:
self.comfyui_process.wait(timeout=5)
except subprocess.TimeoutExpired:
# Forza la terminazione
self.comfyui_process.kill()
self.comfyui_process = None
self.log_message("Processo ComfyUI terminato")
except Exception as e:
self.log_message(f"Errore nella terminazione: {str(e)}")
else:
# Prova a killare qualsiasi processo sulla porta 8188
try:
subprocess.run(['pkill', '-f', 'comfy'], timeout=5)
self.log_message("Terminati processi ComfyUI")
except:
self.log_message("Nessun processo ComfyUI trovato da terminare")
def on_install_comfyui(self, button):
"""Installa ComfyUI nell'ambiente selezionato"""
if not self.selected_conda_env:
self.log_message("Nessun ambiente conda selezionato")
return
env_name, env_path = self.selected_conda_env
self.log_message(f"Installazione ComfyUI nell'ambiente {env_name}...")
def install_comfy():
try:
# Prima installa comfy-cli
cmd1 = ['conda', 'run', '-n', env_name, 'pip', 'install', 'comfy-cli']
result1 = subprocess.run(cmd1, capture_output=True, text=True, timeout=300)
if result1.returncode == 0:
GLib.idle_add(lambda: self.log_message("comfy-cli installato con successo"))
# Poi installa ComfyUI
cmd2 = ['conda', 'run', '-n', env_name, 'comfy', 'install']
result2 = subprocess.run(cmd2, capture_output=True, text=True, timeout=600)
if result2.returncode == 0:
GLib.idle_add(lambda: self.log_message("ComfyUI installato con successo!"))
else:
GLib.idle_add(lambda: self.log_message(f"Errore installazione ComfyUI: {result2.stderr}"))
else:
GLib.idle_add(lambda: self.log_message(f"Errore installazione comfy-cli: {result1.stderr}"))
except subprocess.TimeoutExpired:
GLib.idle_add(lambda: self.log_message("Timeout durante l'installazione"))
except Exception as e:
GLib.idle_add(lambda: self.log_message(f"Errore durante l'installazione: {str(e)}"))
threading.Thread(target=install_comfy, daemon=True).start()
class ComfyUIApp(Adw.Application):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.connect('activate', self.on_activate)
# Configura il style manager per gestire correttamente i temi
self.setup_style_manager()
# Aggiungi azioni per il menu
self.setup_actions()
def setup_style_manager(self):
"""Configura il gestore dello stile per evitare warning"""
style_manager = Adw.StyleManager.get_default()
style_manager.set_color_scheme(Adw.ColorScheme.DEFAULT)
def setup_actions(self):
# Azione About
about_action = Gio.SimpleAction.new("about", None)
about_action.connect("activate", self.on_about_action)
self.add_action(about_action)
# Azione Quit
quit_action = Gio.SimpleAction.new("quit", None)
quit_action.connect("activate", self.on_quit_action)
self.add_action(quit_action)
# Azione Open Folder
open_folder_action = Gio.SimpleAction.new("open_folder", None)
open_folder_action.connect("activate", self.on_open_folder_action)
self.add_action(open_folder_action)
# Shortcut per quit
self.set_accels_for_action("app.quit", ["<primary>q"])
def on_activate(self, app):
print("Avvio ComfyUI Launcher...")
# Crea la finestra principale
self.win = ComfyUILauncher(application=app)
print("Finestra launcher creata")
self.win.present()
print("Launcher presentato")
def on_about_action(self, action, param):
# Mostra dialog About
about = Adw.AboutWindow(
transient_for=self.win,
application_name="ComfyUI Launcher",
application_icon="application-x-executable",
developer_name="ComfyUI Launcher",
version="1.0.0",
developers=["ComfyUI Launcher Team"],
copyright="© 2025 ComfyUI Launcher",
comments="Un launcher GTK per ComfyUI con supporto conda"
)
about.present()
def on_open_folder_action(self, action, param):
"""Apre la cartella ComfyUI"""
try:
# Prova ad aprire la cartella di default di ComfyUI
home_dir = os.path.expanduser("~")
comfy_dir = os.path.join(home_dir, "comfy", "ComfyUI")
if os.path.exists(comfy_dir):
subprocess.run(['xdg-open', comfy_dir])
else:
self.win.log_message("Cartella ComfyUI non trovata")
except Exception as e:
self.win.log_message(f"Errore nell'apertura cartella: {str(e)}")
def on_quit_action(self, action, param):
# Ferma ComfyUI se in esecuzione prima di chiudere
if hasattr(self, 'win') and self.win.comfyui_process:
self.win.on_stop_comfyui(None)
self.quit()
def main():
print("Avvio del ComfyUI Launcher...")
try:
app = ComfyUIApp(application_id="com.example.ComfyUILauncher")
print("Applicazione launcher creata, avvio in corso...")
exit_code = app.run(sys.argv)
print(f"Launcher terminato con codice: {exit_code}")
return exit_code
except Exception as e:
print(f"Errore durante l'esecuzione del launcher: {e}")
import traceback
traceback.print_exc()
return 1
if __name__ == '__main__':
main()

84
pyproject.toml

@ -0,0 +1,84 @@
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "comfyui-launcher"
version = "1.0.0"
description = "A modern GTK4 launcher for ComfyUI with conda environment support"
readme = "README_EN.md"
license = {text = "MIT"}
authors = [
{name = "ComfyUI Launcher Team"},
]
maintainers = [
{name = "ComfyUI Launcher Team"},
]
keywords = ["comfyui", "launcher", "gtk4", "conda", "ai", "stable-diffusion"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: End Users/Desktop",
"License :: OSI Approved :: MIT License",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Multimedia :: Graphics",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
"Environment :: X11 Applications :: GTK",
]
requires-python = ">=3.9"
dependencies = [
"PyGObject>=3.42.0",
]
[project.optional-dependencies]
monitoring = ["psutil>=5.9.0"]
dev = [
"black",
"flake8",
"mypy",
"pytest",
]
[project.urls]
Homepage = "https://github.com/your-username/comfyui-launcher"
Repository = "https://github.com/your-username/comfyui-launcher"
Issues = "https://github.com/your-username/comfyui-launcher/issues"
Documentation = "https://github.com/your-username/comfyui-launcher/blob/main/README_EN.md"
[project.scripts]
comfyui-launcher = "main:main"
[tool.setuptools]
py-modules = ["main"]
[tool.black]
line-length = 88
target-version = ['py39']
include = '\.pyi?$'
extend-exclude = '''
/(
# directories
\.eggs
| \.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| build
| dist
)/
'''
[tool.flake8]
max-line-length = 88
extend-ignore = ["E203", "W503"]
[tool.mypy]
python_version = "3.9"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true

26
requirements.txt

@ -0,0 +1,26 @@
# ComfyUI Launcher Requirements
# Python dependencies for the GTK4 ComfyUI launcher
# Core GTK bindings
PyGObject>=3.42.0
# System monitoring (optional, fallback to system commands if not available)
psutil>=5.9.0
# Note: Additional system dependencies required:
# - GTK4 development libraries
# - Cairo development libraries
# - GObject Introspection development libraries
# - pkg-config
# - Python development headers
#
# Install system dependencies first:
#
# Fedora/RHEL/CentOS:
# sudo dnf install cairo-devel gobject-introspection-devel gtk4-devel pkg-config python3-devel
#
# Debian/Ubuntu:
# sudo apt install libcairo2-dev libgirepository1.0-dev libgtk-4-dev pkg-config python3-dev
#
# Arch Linux:
# sudo pacman -S cairo gobject-introspection gtk4 pkgconf python

35
style.css

@ -0,0 +1,35 @@
/* Stili per il ComfyUI Launcher */
.status-running {
color: #26a269;
}
.status-stopped {
color: #c01c28;
}
.log-view {
font-family: "JetBrains Mono", "Fira Code", "Source Code Pro", monospace;
font-size: 10pt;
background-color: #1e1e1e;
color: #d4d4d4;
}
.environment-frame {
border: 1px solid #3584e4;
border-radius: 6px;
}
.control-button {
margin: 6px;
padding: 12px 24px;
font-weight: bold;
}
.install-button {
background: linear-gradient(to bottom, #62a0ea, #3584e4);
}
.install-button:hover {
background: linear-gradient(to bottom, #74b0fa, #4894f4);
}
Loading…
Cancel
Save