diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..16bd4e2 --- /dev/null +++ b/.env.example @@ -0,0 +1,8 @@ +# Python Configuration +PYTHON_PATH=C:/Path/To/Your/Python/python.exe + +# Email configuration for suggestion system +EMAIL_ADDRESS=your_email@gmail.com +EMAIL_PASSWORD=your_app_password +EMAIL_SMTP_SERVER=smtp.gmail.com +EMAIL_SMTP_PORT=587 diff --git a/README.md b/README.md index e69de29..4ba575b 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,266 @@ +# Python PyQt6 Application Template + +A modern, feature-rich template for building desktop applications with PyQt6. This template provides a solid foundation with theming, internationalization, settings management, and a modular architecture. + +## Features + +- **Modern UI Framework**: Built with PyQt6 for cross-platform compatibility +- **Theme System**: Dark and light themes with easy customization +- **Internationalization**: Multi-language support (English and French included) +- **Settings Management**: Persistent user preferences with QSettings +- **Modular Architecture**: Clean separation of concerns with managers and observers +- **Tabbed Interface**: Flexible tab widget system with customizable positioning +- **Window State Management**: Remembers window size, position, and maximized state +- **Email Integration**: Built-in suggestion/feedback system with secure email configuration +- **Build Automation**: Automated building with PyInstaller +- **Virtual Environment Management**: Automated environment setup + +## Project Structure + +``` +Template/ +├── app/ +│ ├── core/ # Core application managers +│ │ ├── main_manager.py # Singleton manager coordinator +│ │ ├── settings_manager.py # User settings and configuration +│ │ ├── theme_manager.py # Theme and styling management +│ │ ├── language_manager.py # Internationalization +│ │ └── observer_manager.py # Event notification system +│ ├── ui/ +│ │ ├── main_window.py # Main application window +│ │ ├── widgets/ # Custom widgets +│ │ │ └── tabs_widget.py # Customizable tab system +│ │ └── windows/ # Application windows +│ │ ├── settings_window.py +│ │ └── suggestion_window.py +│ └── utils/ +│ └── paths.py # Path utilities for resources +├── data/ +│ ├── assets/ # Icons and images +│ ├── lang/ # Language files (JSON) +│ ├── themes/ # Theme configuration files +│ └── others/ # Default settings +├── tools/ # Build and development tools +│ ├── build.bat/.sh/.command # Platform-specific build script +│ └── open.bat/.sh/.command # Platform-specific development setup +├── config.json # Application configuration +├── requirements.txt # Python dependencies +├── BUILD.spec # PyInstaller specification +└── main.py # Application entry point +``` + +### Development Setup + +1. **Clone/Download** this template +2. **Configure** your application in `config.json`: + ```json + { + "app_name": "YourAppName", + "python_version": "YourPythonVersion", + "app_os": "Windows or Linux or Mac", + "app_version": "YourAppVersion", + "architecture": "x64 or x32", + "icon_path": "data/assets/icon.ico", + "main_script": "main.py" + } + ``` + +3. **Setup environment configuration**: + - Copy `.env.example` to `.env` + - Configure your Python path and email credentials: + ```env + # Python Configuration + PYTHON_PATH=C:/Path/To/Your/Python/python.exe + + # Email Configuration (optional) + EMAIL_ADDRESS=your_email@gmail.com + EMAIL_PASSWORD=your_app_password + EMAIL_SMTP_SERVER=smtp.gmail.com + EMAIL_SMTP_PORT=587 + ``` + - For Gmail, use an [App Password](https://support.google.com/accounts/answer/185833) instead of your regular password + +4. **Run development environment**: + - **Windows**: `tools\open.bat` + - **Linux**: `tools/open.sh` + - **macOS**: `tools/open.command` + + This will: + - Create a virtual environment + - Install dependencies + - Open VS Code with proper environment + +### Building for Production + +- **Windows**: `tools\build.bat` +- **Linux**: `tools/build.sh` +- **macOS**: `tools/build.command` + +This creates a standalone executable in the `build/` directory. + +### Adding Themes + +Create JSON files in `data/themes/`. **Important**: Use the predefined color names as they are used throughout the application's styling system. + +```json +{ + "theme_name": "custom", + "colors": { + "background": "#FFFFFF", // Main background color + "background2": "#F5F5F5", // Secondary background + "background3": "#E0E0E0", // Tertiary background + "font_color": "#000000", // Text color + "selected_icon": "#000000", // Selected icon color + "unselected_icon": "#5D5A5A", // Unselected icon color + "selected_border_icon": "#000000", // Selected border color + "hover_icon": "#000000" // Hover state color + } +} +``` + +**Warning**: Do not change the color property names (`background`, `background2`, etc.) as they are hardcoded in the theme system. Only modify the hex color values. + +### Adding Languages + +Create JSON files in `data/lang/`. **Important**: Use the existing translation keys to ensure proper functionality. + +```json +{ + "lang_name": "Español", + "yes": "Sí", + "no": "No", + "language": "Idioma:", + "settings": "Configuración", + "theme": "Tema:", + "dark_theme": "Tema Oscuro", + "light_theme": "Tema Claro", + "suggestion_text": "¿Tienes una pregunta o idea para mejorar esta aplicación?", + "suggestion_placeholder": "Escribe tu mensaje aquí...", + "send_suggestion": "Enviar", + "sending": "Enviando...", + "success": "Éxito", + "error": "Error", + "suggestion_sent_success": "¡Tu mensaje ha sido enviado exitosamente!", + "suggestion_send_error": "Error al enviar el mensaje. Inténtalo de nuevo más tarde.", + "email_credentials_error": "Credenciales de email no configuradas. Por favor configura tu email y contraseña en el archivo .env." +} +``` + +**Warning**: Do not change the translation keys (left side of the colon) as they are used throughout the application code. Only translate the values (right side). + +## Architecture + +### Manager Pattern + +The application uses a centralized manager system: + +- **MainManager**: Singleton coordinator for all managers +- **SettingsManager**: Handles user preferences and persistence +- **ThemeManager**: Manages themes and styling +- **LanguageManager**: Handles internationalization +- **ObserverManager**: Event notification system + +### Observer Pattern + +Components can subscribe to events: + +```python +self.observer_manager.subscribe(NotificationType.THEME, self.update_theme) +self.observer_manager.subscribe(NotificationType.LANGUAGE, self.update_language) +``` + +### Tab System + +The flexible tab widget supports multiple positioning options: + +```python +# Add a tab with custom positioning +self.side_menu.add_widget( + widget=your_widget, + button_text="", + icon_path=paths.get_asset_svg_path("icon_name"), + position=ButtonPosition.CENTER +) +``` + +## Email Integration + +The template includes a suggestion system with email capabilities. Configure in your `.env` file: + +**Security Note**: Never commit your `.env` file to version control. It's already included in `.gitignore`. + +For Gmail users: +- Enable 2-factor authentication +- Generate an App Password specifically for this application +- Use the App Password in the `EMAIL_PASSWORD` field + +## Customization + +### Adding New Windows + +1. Create window class inheriting from `QWidget` +2. Subscribe to language notifications +3. Add to main window tab system + +```python +class YourWindow(QWidget): + def __init__(self, parent=None): + super().__init__(parent) + self.main_manager = MainManager.get_instance() + # Subscribe to notifications + self.observer_manager.subscribe(NotificationType.LANGUAGE, self.update_language) + self.setup_ui() +``` + +### Custom Widgets + +Place custom widgets in `app/ui/widgets/` and follow the existing patterns for theme integration. + +## Dependencies + +- **PyQt6**: Modern GUI framework +- **pyinstaller**: Executable building +- **python-dotenv**: Environment variable management + +Add additional dependencies to `requirements.txt`. + +## Building + +The build system automatically: +- Creates virtual environments per architecture +- Installs dependencies +- Builds with PyInstaller +- Names executables with config.json +- Includes all assets and data files + +## Cross-Platform Notes + +The template supports multiple platforms with platform-specific scripts: +- **Windows**: Uses `.bat` files +- **Linux**: Uses `.sh` files +- **macOS**: Uses `.command` files + +Adjust config.json for your target platform. + +## License + +MIT License - see LICENSE file for details. + +## Contributing + +1. Fork the repository +2. Create a feature branch +3. Make your changes +4. Test thoroughly +5. Submit a pull request + +## Support + +For issues or questions: +- Check existing issues +- Create detailed bug reports +- Include system information and error logs + +--- + +**Happy coding!** 🚀 \ No newline at end of file diff --git a/app/ui/windows/suggestion_window.py b/app/ui/windows/suggestion_window.py index 69c12c0..fc8d7dc 100644 --- a/app/ui/windows/suggestion_window.py +++ b/app/ui/windows/suggestion_window.py @@ -5,8 +5,12 @@ import smtplib import os from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart +from dotenv import load_dotenv from app.core.main_manager import MainManager, NotificationType +# Load environment variables from .env file +load_dotenv() + class EmailSender(QThread): success = pyqtSignal() error = pyqtSignal(str) @@ -19,14 +23,13 @@ class EmailSender(QThread): def run(self): try: # Get email configuration from environment variables - password = 'xprqegxuqixgljyi' - email = 'louismazindev@gmail.com' - smtp_server = 'smtp.gmail.com' - smtp_port = 587 + email = os.getenv('EMAIL_ADDRESS') + password = os.getenv('EMAIL_PASSWORD') + smtp_server = os.getenv('EMAIL_SMTP_SERVER', 'smtp.gmail.com') + smtp_port = int(os.getenv('EMAIL_SMTP_PORT', '587')) - if not password: - # Fallback to simulation if no credentials are configured - self._simulate_email_sending() + if not email or not password: + self.error.emit("password") return # Create message @@ -49,19 +52,8 @@ class EmailSender(QThread): server.quit() self.success.emit() - except Exception as e: - self.error.emit() - - def _simulate_email_sending(self): - """Fallback simulation when no email credentials are configured""" - time.sleep(2) # Simulate network delay - - print("=== EMAIL SIMULATION (No credentials configured) ===") - print(f"Subject: {self.subject}") - print(f"Message: {self.message}") - print("=" * 55) - - self.success.emit() + except Exception: + self.error.emit("") class SuggestionWindow(QWidget): def __init__(self, parent=None): @@ -132,13 +124,16 @@ class SuggestionWindow(QWidget): self.language_manager.get_text("suggestion_sent_success")) self.text_edit.clear() - def on_email_error(self): + def on_email_error(self, error): self.send_button.setEnabled(True) self.send_button.setText(self.language_manager.get_text("send_suggestion")) - + if error == "password": + message = self.language_manager.get_text("email_credentials_error") + else: + message = self.language_manager.get_text("suggestion_send_error") QMessageBox.critical(self, - self.language_manager.get_text("error"), - f"{self.language_manager.get_text('suggestion_send_error')}") + self.language_manager.get_text("error"), + message) def update_language(self): self.title_label.setText(self.language_manager.get_text("suggestion_text")) diff --git a/config.json b/config.json index 2462d61..c365fe7 100644 --- a/config.json +++ b/config.json @@ -5,6 +5,5 @@ "app_version": "1.0.0", "architecture": "x64", "icon_path": "data/assets/icon.ico", - "main_script": "main.py", - "python_path": "C:/Logiciels/Python/x64/3.11.7/python.exe" + "main_script": "main.py" } \ No newline at end of file diff --git a/data/assets/settings.svg b/data/assets/settings.svg index 3bfe869..c67bfb2 100644 --- a/data/assets/settings.svg +++ b/data/assets/settings.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/data/assets/suggestion.svg b/data/assets/suggestion.svg index 6634fc4..f383c8a 100644 --- a/data/assets/suggestion.svg +++ b/data/assets/suggestion.svg @@ -1,8 +1,8 @@ - + - + diff --git a/data/lang/en.json b/data/lang/en.json index 48dce8e..1f76faa 100644 --- a/data/lang/en.json +++ b/data/lang/en.json @@ -14,5 +14,6 @@ "success": "Success", "error": "Error", "suggestion_sent_success": "Your message has been sent successfully!", - "suggestion_send_error": "Error sending message. Try again later." + "suggestion_send_error": "Error sending message. Try again later.", + "email_credentials_error": "Email credentials not configured. Please set your email and password in the .env file." } \ No newline at end of file diff --git a/data/lang/fr.json b/data/lang/fr.json index 7897f6c..8677160 100644 --- a/data/lang/fr.json +++ b/data/lang/fr.json @@ -14,5 +14,6 @@ "success": "Succès", "error": "Erreur", "suggestion_sent_success": "Votre message a été envoyé avec succès !", - "suggestion_send_error": "Erreur lors de l'envoi du message. Essayez à nouveau plus tard." + "suggestion_send_error": "Erreur lors de l'envoi du message. Essayez à nouveau plus tard.", + "email_credentials_error": "Identifiants de messagerie non configurés. Veuillez définir votre email et mot de passe dans le fichier .env." } \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 69352a3..2fc62e6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ PyQt6 -pyinstaller \ No newline at end of file +pyinstaller +python-dotenv \ No newline at end of file diff --git a/tools/build.bat b/tools/build.bat index 49fb6b0..8e53c7b 100644 --- a/tools/build.bat +++ b/tools/build.bat @@ -4,6 +4,13 @@ setlocal enabledelayedexpansion REM === PATH SETUP === set PARENT_DIR=%~dp0.. set CONFIG_FILE=%PARENT_DIR%\config.json +set ENV_FILE=%PARENT_DIR%\.env + +REM Check if .env file exists +if not exist "%ENV_FILE%" ( + echo [ERROR] .env file not found. Please copy .env.example to .env and configure it. + exit /b 1 +) REM === Extract values from config.json === for /f "delims=" %%i in ('powershell -NoProfile -Command ^ @@ -14,8 +21,9 @@ for /f "delims=" %%i in ('powershell -NoProfile -Command ^ "Get-Content '%CONFIG_FILE%' | ConvertFrom-Json | Select-Object -ExpandProperty app_name"') do set APP_NAME=%%i for /f "delims=" %%i in ('powershell -NoProfile -Command ^ "Get-Content '%CONFIG_FILE%' | ConvertFrom-Json | Select-Object -ExpandProperty architecture"') do set ARCHITECTURE=%%i -for /f "delims=" %%i in ('powershell -NoProfile -Command ^ - "Get-Content '%CONFIG_FILE%' | ConvertFrom-Json | Select-Object -ExpandProperty python_path"') do set SYSTEM_PYTHON=%%i + +REM === Extract python path from .env file === +for /f "usebackq tokens=2 delims==" %%i in (`findstr "PYTHON_PATH" "%ENV_FILE%"`) do set SYSTEM_PYTHON=%%i set VENV_PATH=%PARENT_DIR%\WINenv_%ARCHITECTURE% set EXE_NAME=%APP_NAME%-Windows-%ARCHITECTURE% diff --git a/tools/open.bat b/tools/open.bat index dd52d62..0878c5c 100644 --- a/tools/open.bat +++ b/tools/open.bat @@ -5,6 +5,13 @@ REM Set file paths set ROOT_DIR=%~dp0.. set CONFIG_FILE=%ROOT_DIR%\config.json set REQUIREMENTS=%ROOT_DIR%\requirements.txt +set ENV_FILE=%ROOT_DIR%\.env + +REM Check if .env file exists +if not exist "%ENV_FILE%" ( + echo [ERROR] .env file not found. Please copy .env.example to .env and configure it. + exit /b 1 +) REM Extract config.json fields using PowerShell for /f "delims=" %%i in ('powershell -NoProfile -Command ^ @@ -12,9 +19,9 @@ for /f "delims=" %%i in ('powershell -NoProfile -Command ^ for /f "delims=" %%i in ('powershell -NoProfile -Command ^ "Get-Content '%CONFIG_FILE%' | ConvertFrom-Json | Select-Object -ExpandProperty architecture"') do set ARCHITECTURE=%%i - -for /f "delims=" %%i in ('powershell -NoProfile -Command ^ - "Get-Content '%CONFIG_FILE%' | ConvertFrom-Json | Select-Object -ExpandProperty python_path"') do set PYTHON_EXEC=%%i + +REM Extract python path from .env file +for /f "usebackq tokens=2 delims==" %%i in (`findstr "PYTHON_PATH" "%ENV_FILE%"`) do set PYTHON_EXEC=%%i REM Construct python executable path set ENV_NAME=WINenv_%ARCHITECTURE% @@ -22,7 +29,7 @@ set ENV_PATH=%ROOT_DIR%\%ENV_NAME% if not exist "%PYTHON_EXEC%" ( echo [ERROR] Python introuvable à: %PYTHON_EXEC% - echo Veuillez vérifier votre config.json ou le dossier d'installation. + echo Veuillez vérifier votre .env ou le dossier d'installation. exit /b 1 )