Remove obsolete optimization and resource monitoring documentation; update scenario management to ensure user directory saving and template protection.

This commit is contained in:
2025-08-06 17:33:03 +02:00
parent a31b01238a
commit 1e8123efdb
11 changed files with 546 additions and 521 deletions
-111
View File
@@ -1,111 +0,0 @@
# VisionFlow Automator - Performance Optimizations
## Overview
This document outlines the performance and memory optimizations implemented to prevent the application from being killed or stalled during scenario execution.
## Key Optimizations Implemented
### 1. Memory Management
- **Template Caching**: Added `TemplateCache` class to cache loaded CV2 templates instead of reloading from disk every loop iteration
- **Screenshot Caching**: Implemented screenshot caching with 50ms duration to reduce memory allocations
- **Resource Cleanup**: Added proper cleanup in `cleanup_resources()` method and `closeEvent()`
- **Garbage Collection**: Strategic `gc.collect()` calls to force memory cleanup at appropriate times
- **Pixmap Memory Management**: Optimized image preview handling to prevent large pixmap memory leaks
### 2. Performance Improvements
- **Optimized Loop Structure**: Redesigned automation loop to be more efficient
- **Step Cooldown System**: Prevents rapid re-execution of the same step (1-second cooldown)
- **Priority Execution**: Only executes one step per loop iteration to prevent blocking
- **Dynamic Sleep**: Adjusts sleep time based on loop performance (0.05-0.2s)
- **Performance Monitoring**: Added loop time tracking and warnings for slow performance
### 3. Threading Improvements
- **Proper Thread Management**: Added timeout for thread joining in `stop_automation()`
- **Background Processing**: Improved worker thread handling with better error recovery
- **Non-blocking Operations**: Reduced blocking operations in the main thread
### 4. UI Optimizations
- **Reduced Logging**: Changed default log level from DEBUG to INFO to reduce I/O overhead
- **Efficient Image Previews**: Optimized image scaling and memory usage in dialogs
- **State Update Throttling**: Reduced frequency of UI state updates
### 5. Resource Monitoring
- **Performance Timer**: Added 10-second monitoring timer to track application health
- **Memory Usage Tracking**: Optional psutil integration for detailed memory monitoring
- **Cache Size Monitoring**: Tracks template cache size and warns when it grows large
### 6. Error Handling
- **Graceful Degradation**: Better error handling in screenshot capture and template matching
- **Resource Recovery**: Automatic cleanup on errors to prevent resource leaks
- **Hotkey Error Handling**: Continues operation even if hotkey setup fails
## Configuration Changes
### PyAutoGUI Optimizations
- Set `pyautogui.PAUSE = 0.01` (reduced from default 0.1s)
- Set `pyautogui.MINIMUM_DURATION = 0` for faster actions
- Kept `pyautogui.FAILSAFE = False` for automation reliability
### Screenshot Optimization
- Added minimum size validation (10x10 pixels)
- Improved tkinter screenshot tool with better UX
- Memory-efficient PIL image handling with proper cleanup
### Template Matching
- LRU cache with automatic cleanup of old entries
- Maximum cache size of 50 templates
- Force reload option for template updates
## Performance Targets
### Memory Usage
- Template cache limited to 50 entries
- Screenshot cache duration: 50ms
- Automatic cleanup every 100 loop iterations
- Garbage collection after major operations
### Timing
- Target loop time: 50-200ms
- Step cooldown: 1 second
- Performance warning threshold: 1 second average loop time
- Monitoring interval: 10 seconds
### Thread Safety
- Worker thread timeout: 2 seconds
- Daemon threads for automatic cleanup
- Proper resource locking where needed
## Usage Recommendations
1. **Monitor Performance**: Check logs for performance warnings
2. **Resource Management**: Regularly restart long-running sessions
3. **Template Optimization**: Use appropriately sized template images
4. **Step Design**: Avoid too many simultaneous image detections
5. **System Resources**: Ensure adequate RAM for screenshot operations
## Future Improvements
1. **Multi-threading**: Consider separate threads for image processing
2. **Image Compression**: Compress cached templates to save memory
3. **Region Optimization**: Use smaller detection regions when possible
4. **GPU Acceleration**: Consider OpenCV GPU operations for template matching
5. **Background Processing**: Process non-critical operations in background
## Troubleshooting
### High Memory Usage
- Check template cache size in logs
- Reduce number of simultaneous steps
- Restart application periodically
### Slow Performance
- Check average loop times in logs
- Reduce image template sizes
- Simplify detection regions
- Consider fewer simultaneous detections
### Application Crashes
- Check log files for error patterns
- Monitor system memory usage
- Verify image file integrity
- Check for corrupted templates
-71
View File
@@ -1,71 +0,0 @@
# VisionFlow Automator - Performance Optimization Summary
## Optimizations Applied
**Memory Management**
- Added template caching system to prevent repeated file I/O
- Implemented screenshot caching with 50ms duration
- Added proper resource cleanup and garbage collection
- Optimized image preview handling to prevent memory leaks
**Performance Improvements**
- Redesigned automation loop for better efficiency
- Added step cooldown system (1-second minimum between executions)
- Implemented dynamic sleep timing based on performance
- Added performance monitoring and warning system
**Threading & Stability**
- Improved worker thread management with proper cleanup
- Added timeout handling for thread termination
- Better error handling to prevent application crashes
- Non-blocking operations in main UI thread
**Resource Optimization**
- Reduced logging verbosity to decrease I/O overhead
- Optimized PyAutoGUI settings for faster execution
- Improved screenshot selection tool with better UX
- Added periodic cleanup every 100 loop iterations
## Key Features Added
### TemplateCache Class
- LRU cache for CV2 template images
- Automatic cleanup of old entries
- Maximum 50 templates cached
- Memory-efficient template loading
### Performance Monitoring
- Loop time tracking and warnings
- Memory usage monitoring
- 10-second monitoring intervals
- Automatic performance alerts
### Optimized Automation Loop
- Priority-based step execution
- Screenshot caching and reuse
- Improved error handling and recovery
- Dynamic timing adjustments
## Expected Results
- **Reduced Memory Usage**: Template caching and proper cleanup
- **Faster Performance**: Optimized loops and reduced I/O
- **Better Stability**: Improved error handling and resource management
- **No More Stalling**: Non-blocking operations and better threading
## Configuration Changes
```python
# PyAutoGUI optimizations
pyautogui.PAUSE = 0.01 # Faster actions
pyautogui.MINIMUM_DURATION = 0 # No minimum delays
# Logging optimization
logging.basicConfig(level=logging.INFO) # Reduced verbosity
# Template cache settings
max_cache_size = 50 # Maximum cached templates
cache_cleanup_threshold = 25% # When to clean old entries
```
The optimized application should now run more efficiently without getting killed or stalled during scenario execution.
+197 -45
View File
@@ -1,62 +1,214 @@
# VisionFlowAutomator # VisionFlow Automator
VisionFlowAutomator is a powerful desktop automation tool that lets you create, edit, and run automation scenarios based on image recognition and GUI actions. With an intuitive graphical interface, you can visually define workflows that interact with any application or window on your system. VisionFlow Automator is a powerful desktop automation tool that lets you create, edit, and run automation scenarios based on image recognition and GUI actions. With an intuitive graphical interface, you can visually define workflows that interact with any application or window on your system.
## Features ## 🌟 Features
- **Scenario Management**: Create, edit, rename, import, export, and organize automation scenarios. - **Scenario Management**: Create, edit, rename, import, export, and organize automation scenarios
- **Step-Based Automation**: Each scenario consists of multiple steps, each with its own set of images and actions. - **Template Library**: Get started quickly with pre-built scenario templates
- **Screenshot-Based Image Matching**: Take region-based screenshots as image triggers for steps. Adjustable sensitivity for robust detection. - **Step-Based Automation**: Each scenario consists of multiple steps, each with its own set of images and actions
- **Flexible Actions**: Automate clicks (with position modes), key presses, scrolling, and delays. Actions can be chained per step. - **Screenshot-Based Image Matching**: Take region-based screenshots as image triggers for steps with adjustable sensitivity
- **Window Targeting**: Run automations on the entire screen or a specific open window. - **Flexible Actions**: Automate clicks (with position modes), key presses, scrolling, and delays
- **Hotkey Control**: Start/stop automation instantly with a global hotkey (default: F9). - **Window Targeting**: Run automations on the entire screen or a specific open window
- **Visual Step Editor**: Add, edit, reorder, and preview step images and actions with a modern PyQt6 interface. - **Hotkey Control**: Start/stop automation instantly with a global hotkey (default: F9)
- **Import/Export**: Share or back up scenarios as ZIP files. - **Visual Step Editor**: Add, edit, reorder, and preview step images and actions with a modern PyQt6 interface
- **Persistent State**: Auto-saves all changes and remembers your last scenario and window selection. - **Import/Export**: Share or back up scenarios as ZIP files
- **Logging**: Detailed logs for troubleshooting and auditing automation runs. - **Persistent State**: Auto-saves all changes and remembers your last scenario and window selection
- **Theme Support**: Light, dark, and system theme modes with instant switching
- **Resource Monitoring**: Real-time performance and memory usage tracking
- **Comprehensive Logging**: Detailed logs for troubleshooting and auditing automation runs
## How It Works ## 🚀 Quick Start
1. **Create a Scenario**: Define a new scenario and add steps. ### Prerequisites
2. **Add Step Images**: For each step, take a screenshot of the region to match. Multiple images per step are supported.
3. **Define Actions**: Assign actions (click, key, scroll, delay) to perform when images are detected.
4. **Set Conditions**: Choose whether all images (AND) or any image (OR) must be detected to trigger actions.
5. **Target Window**: Select the window or use the entire screen for automation.
6. **Run Automation**: Start/stop with the hotkey or UI button. The app continuously looks for image matches and performs actions as defined.
## Requirements
- Python 3.11+ - Python 3.11+
- PyQt6 - Required Python packages (see requirements.txt)
- opencv-python
- pyautogui
- pynput
- pygetwindow
- numpy
- Pillow
Install dependencies with: ### Installation
```bash
pip install -r requirements.txt
```
## Running the App 1. Clone or download this repository
2. Install dependencies:
1. Ensure all dependencies are installed.
2. Run the main script:
```bash ```bash
python main.py pip install -r requirements.txt
``` ```
## Tips ### Running the App
- Use high-quality, tightly-cropped reference images for best detection results.
- Adjust sensitivity per image for robust matching. ```bash
- Use the import/export feature to share scenarios between machines. python main.py
- All changes are saved automatically; no need to manually save. ```
## 📋 How It Works
1. **Choose a Template or Create New**: Start with a pre-built template or create your own scenario
2. **Add Step Images**: For each step, take screenshots of UI elements to detect
3. **Define Actions**: Assign actions (click, key, scroll, delay) to perform when images are found
4. **Set Conditions**: Choose whether all images (AND) or any image (OR) must be detected
5. **Target Window**: Select a specific window or use the entire screen
6. **Run Automation**: Start/stop with the hotkey (F9) or UI button
## 📚 Template Library
VisionFlow Automator includes ready-to-use templates in the `/templates/` folder:
### 🖱️ Simple Click Example
Perfect for beginners learning basic automation:
- **Purpose**: Demonstrates basic clicking with image detection
- **Actions**: Left-click at center of detected images with timing delays
- **Use Cases**: Button clicking, basic UI automation, learning the system
### 🌐 Web Browser Example
Common web browsing automation patterns:
- **Actions**: Page refresh (F5), scrolling, navigation (Alt+Left)
- **Use Cases**: Automated web browsing, content monitoring, web testing
- **Compatible**: Chrome, Firefox, Edge, Safari
### 🎮 Gaming Example
Game automation patterns (use responsibly):
- **Actions**: Attack (Space), abilities (number keys), movement (WASD)
- **Use Cases**: RPG/MMO automation, action games
- **Safety**: Includes warnings about game terms of service
## 🛠️ Advanced Features
### Theme Support
- **Light/Dark/System modes**: Automatic theme switching based on system preferences
- **Instant application**: Themes apply immediately across all windows
- **Persistent settings**: Your theme preference is saved
### Resource Monitoring
- **Real-time metrics**: Memory usage, CPU usage, GPU information
- **Performance tracking**: Loop times, cache statistics
- **Configurable intervals**: Adjust monitoring frequency from 0.5s to 10s
### Window Management
- **Geometry persistence**: Window size and position are remembered
- **Multi-monitor support**: Works across multiple displays
- **Exact positioning**: Precise window placement restoration
## 📝 Requirements
```
PyQt6>=6.0.0
opencv-python>=4.5.0
pyautogui>=0.9.50
pynput>=1.7.0
pygetwindow>=0.0.9
numpy>=1.21.0
Pillow>=8.0.0
```
## 🎯 Tips for Best Results
### Image Recognition
- Use high-quality, tightly-cropped reference images
- Adjust sensitivity per image for robust matching (0.5-1.0 range)
- Test images in the same environment where automation will run
- Avoid images with frequently changing content (timestamps, dynamic text)
### Action Timing
- Add appropriate delays between actions to prevent overwhelming target applications
- Use longer delays after heavy actions (opening applications, loading pages)
- Test with different timing values to find optimal performance
### Window Targeting
- Specify target windows when possible for better performance
- Use "Entire Screen" for cross-application automation
- Refresh window list if target application isn't visible
### Scenario Organization
- Use descriptive names for scenarios and steps
- Group related actions within single steps when logical
- Export important scenarios as backups
- Document complex scenarios with clear step names
## 🔧 Configuration
### Settings Access
Access settings through the "Settings" button in the main window:
- **Theme**: Choose between Light, Dark, or System theme
- **Logging Level**: Adjust verbosity from DEBUG to CRITICAL
- **Resource Monitoring**: Configure update intervals and display options
### File Locations
- **User Scenarios**: Stored in system config directory
- **Templates**: Located in `/templates/` folder within application directory
- **Configuration**: Window geometry and preferences saved automatically
- **Logs**: Application logs for troubleshooting
## 🚦 Safety Guidelines
### General Usage
- Always test automation in safe environments first
- Use appropriate delays to avoid overwhelming target applications
- Monitor automation behavior to ensure it works as expected
- Keep backup copies of important scenarios
### Gaming Automation
- **Check game policies**: Many games prohibit automation tools
- **Respect fair play**: Don't use for unfair competitive advantages
- **Test safely**: Practice in single-player or private environments
- **Be considerate**: Avoid disrupting other players' experiences
### Application Automation
- **Respect terms of service**: Check if automation is permitted
- **Rate limiting**: Use delays to avoid being detected as bot traffic
- **Error handling**: Monitor for unexpected application behavior
- **Data safety**: Be cautious with automation that handles sensitive information
## 🐛 Troubleshooting
### Common Issues
**Automation not starting:**
- Check that a scenario is selected
- Verify target window is available
- Ensure required dependencies are installed
**Images not detected:**
- Adjust sensitivity settings (try lower values like 0.7-0.8)
- Retake screenshots in the same environment
- Check that target window matches screenshot conditions
**Performance issues:**
- Reduce resource monitoring frequency
- Close unnecessary applications
- Use window targeting instead of full screen
- Optimize scenario step timing
**Application crashes:**
- Check logs for detailed error information
- Verify all dependencies are correctly installed
- Ensure sufficient system memory is available
- Try running with administrator privileges if needed
### Debug Information
- Enable DEBUG logging level for detailed execution information
- Check resource monitoring for performance bottlenecks
- Use step-by-step testing to isolate issues
- Export scenarios before major changes as backups
## 📄 License
## License
MIT License MIT License
--- ---
VisionFlow Automator — Automate anything you can see! ## 🤝 Contributing
Contributions are welcome! Whether it's:
- Bug reports and fixes
- New template scenarios
- Feature enhancements
- Documentation improvements
- Performance optimizations
## 📞 Support
For issues, questions, or feature requests, please use the project's issue tracker.
---
**VisionFlow Automator** — Automate anything you can see! 🎯
-90
View File
@@ -1,90 +0,0 @@
# Resource Usage Display - Implementation Summary
## ✅ **Features Successfully Added**
### 🎯 **Main UI Enhancements**
- **Resource Usage Group Box**: New section displaying real-time resource metrics
- **Toggle Button**: Hide/Show resources button to save screen space
- **Color-Coded Indicators**: Visual feedback for performance status
- **Interactive Help**: Click to get psutil installation instructions
### 📊 **Monitoring Metrics**
1. **Memory Usage**: Process memory in MB and percentage
2. **CPU Usage**: Process CPU utilization percentage
3. **System Memory**: Overall system memory usage and available space
4. **Cache Information**: Template cache size and cooldown entries
5. **Performance**: Average automation loop execution time
### 🔄 **Real-Time Updates**
- **2-Second Refresh**: Resource display updates every 2 seconds
- **Non-Blocking**: Updates don't interfere with automation performance
- **Automatic Monitoring**: Starts immediately when application launches
### 🎨 **Visual Design**
- **Color-Coded Status**:
- 🟢 Green: Normal/Good performance
- 🟡 Orange: Warning levels
- 🔴 Red: High usage/Performance issues
- ⚫ Gray: Unavailable metrics
- **Compact Layout**: Fits seamlessly into existing UI
- **Professional Styling**: Consistent with application theme
### 💡 **Smart Features**
- **Fallback Mode**: Works without psutil, shows basic cache information
- **Enhanced Mode**: Full system metrics when psutil is installed
- **Error Handling**: Graceful degradation if monitoring fails
- **Installation Guide**: Built-in help for psutil setup
## 🚀 **Benefits**
### For Performance Monitoring
- **Real-Time Visibility**: See exactly how much resources the app uses
- **Performance Bottlenecks**: Identify slow automation loops
- **Memory Leak Detection**: Monitor memory usage over time
- **System Impact**: Understand effect on overall system performance
### For Troubleshooting
- **Quick Diagnosis**: Color-coded warnings for immediate issue identification
- **Cache Monitoring**: Track template cache efficiency
- **Resource Optimization**: Data to optimize scenario performance
- **System Health**: Monitor system memory and CPU usage
## 📝 **Usage Instructions**
### Basic Usage
1. **View Resources**: Resource panel is visible by default at the bottom of the main window
2. **Toggle Display**: Click "Hide Resources" button to minimize screen usage
3. **Monitor Status**: Watch color changes for performance alerts
### Enhanced Monitoring
1. **Install psutil**: Run `pip install psutil` (already added to requirements.txt)
2. **Restart App**: Close and reopen VisionFlow Automator
3. **Full Metrics**: All detailed system information will be displayed
### Reading the Display
- **Memory**: Shows process memory usage (green < 10%, red > 10%)
- **CPU**: Shows process CPU usage (green < 50%, red > 50%)
- **System**: Shows system memory usage (green < 85%, red > 85%)
- **Cache**: Shows template cache size (blue normal, orange > 20 entries)
- **Performance**: Shows loop execution time (green < 500ms, red > 500ms)
## 🔧 **Technical Implementation**
### Code Changes
- Enhanced `get_memory_usage()` method with comprehensive metrics
- Added `_update_resource_display()` for UI updates
- Modified `_monitor_performance()` for real-time monitoring
- Added resource display widgets to main UI layout
- Implemented toggle functionality for space-saving
### Error Handling
- Graceful fallback when psutil unavailable
- Error display in resource panel for troubleshooting
- Maintains basic functionality even if monitoring fails
### Performance Impact
- Minimal overhead (2-second update cycle)
- Non-blocking UI updates
- Optimized memory usage for monitoring itself
The resource usage display provides valuable real-time insights into application performance and helps users optimize their automation scenarios for better efficiency and system resource management.
-143
View File
@@ -1,143 +0,0 @@
# Resource Usage Monitoring - VisionFlow Automator
## Overview
The VisionFlow Automator now includes real-time resource usage monitoring displayed directly in the UI. This feature helps users monitor the application's performance and system impact.
## Features Added
### 🔍 **Resource Usage Display**
A new "Resource Usage" group box has been added to the main UI showing:
#### Memory Usage
- **Process Memory**: Shows the application's memory usage in MB and percentage of system memory
- **Color-coded warnings**: Green for normal usage, red for high usage (>10% of system memory)
#### CPU Usage
- **Process CPU**: Shows the application's CPU usage percentage
- **Color-coded warnings**: Green for normal usage, red for high usage (>50%)
#### System Information
- **System Memory**: Shows overall system memory usage percentage and available memory in GB
- **Color-coded warnings**: Green for normal, red when system memory usage exceeds 85%
#### Cache Information
- **Template Cache**: Number of cached CV2 templates
- **Cooldown Entries**: Number of active step cooldowns
- **Color-coded status**: Blue for normal, orange when template cache exceeds 20 entries
#### Performance Metrics
- **Loop Time**: Average automation loop execution time in milliseconds
- **Color-coded performance**: Green for fast loops (<500ms), red for slow loops (>500ms)
### 🎛️ **Controls**
#### Toggle Button
- **Hide/Show Resources**: Button to toggle the visibility of resource usage information
- **Space-saving**: Users can hide the resource display if they don't need it
- **Tooltip**: Provides information about psutil installation for enhanced monitoring
#### Interactive Elements
- **Clickable Labels**: When psutil is not installed, clicking on resource labels shows installation instructions
- **Installation Guide**: Built-in dialog explaining how to install psutil for enhanced monitoring
### 📊 **Monitoring Levels**
#### Basic Monitoring (Without psutil)
When psutil is not installed, the display shows:
- Template cache size
- Cooldown entries count
- Basic performance metrics
- "N/A" for system metrics with installation instructions
#### Enhanced Monitoring (With psutil)
When psutil is installed (`pip install psutil`), the display shows:
- Detailed process memory usage
- CPU usage percentage
- System memory statistics
- Available system memory
- Process performance metrics
### ⚙️ **Technical Details**
#### Update Frequency
- **Real-time Updates**: Resource display updates every 2 seconds
- **Responsive UI**: Non-blocking updates that don't interfere with automation
- **Performance Optimized**: Minimal overhead from monitoring
#### Color Coding System
- **🟢 Green**: Normal/Good performance
- **🟡 Orange/Yellow**: Warning levels
- **🔴 Red**: High usage/Performance issues
- **⚫ Gray**: Unavailable/Error states
#### Error Handling
- **Graceful Degradation**: Shows basic info if detailed monitoring fails
- **Error Display**: Shows error messages for troubleshooting
- **Fallback Information**: Always shows cache and performance data
### 🎯 **Benefits**
#### For Users
- **Real-time Monitoring**: See exactly how much resources the app is using
- **Performance Insights**: Identify when the app is running slowly
- **System Impact**: Understand the app's impact on overall system performance
- **Troubleshooting**: Quickly identify memory leaks or performance issues
#### For Developers
- **Performance Metrics**: Built-in performance profiling
- **Memory Leak Detection**: Monitor memory usage over time
- **Cache Optimization**: Track template cache efficiency
- **System Resources**: Monitor system-wide impact
### 📋 **Usage Instructions**
#### Basic Usage
1. **View Resources**: Resource usage is displayed by default in the main window
2. **Toggle Display**: Click "Hide Resources" to save screen space
3. **Monitor Performance**: Watch for color changes indicating performance issues
#### Enhanced Monitoring Setup
1. **Install psutil**: Run `pip install psutil` in your Python environment
2. **Restart Application**: Close and reopen VisionFlow Automator
3. **Enhanced Display**: All metrics will now show detailed system information
#### Interpreting Metrics
- **Memory < 100MB**: Normal usage for typical scenarios
- **CPU < 20%**: Normal usage during automation
- **Loop Time < 200ms**: Good performance
- **Cache < 20 entries**: Normal template usage
### 🚨 **Warning Thresholds**
#### Memory Warnings
- **Process Memory > 10%**: High memory usage warning
- **System Memory > 85%**: System memory critical
#### Performance Warnings
- **CPU > 50%**: High CPU usage
- **Loop Time > 500ms**: Performance degradation
- **Cache > 20 entries**: Large template cache
### 🔧 **Troubleshooting**
#### High Memory Usage
- Check for memory leaks in long-running sessions
- Clear template cache periodically
- Reduce number of simultaneous image templates
#### High CPU Usage
- Reduce automation frequency
- Optimize image template sizes
- Check for infinite loops in scenarios
#### Slow Performance
- Monitor loop times for bottlenecks
- Reduce screenshot frequency
- Optimize template matching regions
#### Missing psutil
- Install with: `pip install psutil`
- Click on gray resource labels for installation instructions
- Restart application after installation
The resource monitoring feature provides valuable insights into the application's performance and helps users optimize their automation scenarios for better efficiency.
+187 -30
View File
@@ -678,29 +678,46 @@ class Scenario:
def save(self): def save(self):
""" """
Save the scenario to disk as a JSON file. Save the scenario to disk as a JSON file in the user's scenarios directory.
Always saves to the user directory, never to pre-made scenarios.
""" """
try: try:
scenario_dir = self.get_scenario_dir() # Always save to user directory, even if originally loaded from pre-made
scenario_dir = os.path.join(CONFIG_DIR, self.name)
if not os.path.exists(scenario_dir): if not os.path.exists(scenario_dir):
os.makedirs(scenario_dir) os.makedirs(scenario_dir, exist_ok=True)
# If this scenario was originally from pre-made folder and doesn't exist in user folder,
# copy all assets first
if not os.path.exists(os.path.join(scenario_dir, 'scenario.json')):
self.copy_to_user_scenarios()
with open(os.path.join(scenario_dir, 'scenario.json'), 'w') as f: with open(os.path.join(scenario_dir, 'scenario.json'), 'w') as f:
json.dump(self.to_dict(), f, indent=2) json.dump(self.to_dict(), f, indent=2)
logger.info(f"Scenario '{self.name}' saved.") logger.info(f"Scenario '{self.name}' saved to user directory.")
except Exception as e: except Exception as e:
logger.error(f"Failed to save scenario '{self.name}': {e}") logger.error(f"Failed to save scenario '{self.name}': {e}")
@staticmethod @staticmethod
def load(name): def load(name, from_premade=False):
""" """
Load a scenario from disk by name. Load a scenario from disk by name.
If from_premade is True, loads from the pre-made scenarios folder.
""" """
try: try:
scenario_dir = os.path.join(CONFIG_DIR, name) if from_premade:
with open(os.path.join(scenario_dir, 'scenario.json'), 'r') as f: scenario_dir = os.path.join(os.path.dirname(__file__), 'templates', name)
else:
scenario_dir = os.path.join(CONFIG_DIR, name)
scenario_file = os.path.join(scenario_dir, 'scenario.json')
if not os.path.exists(scenario_file):
logger.error(f"Scenario file not found: {scenario_file}")
return None
with open(scenario_file, 'r') as f:
scenario = Scenario.from_dict(json.load(f)) scenario = Scenario.from_dict(json.load(f))
logger.info(f"Scenario '{name}' loaded.") logger.info(f"Scenario '{name}' loaded from {'pre-made' if from_premade else 'user'} directory.")
return scenario return scenario
except Exception as e: except Exception as e:
logger.error(f"Failed to load scenario '{name}': {e}") logger.error(f"Failed to load scenario '{name}': {e}")
@@ -709,9 +726,57 @@ class Scenario:
@staticmethod @staticmethod
def list_all(): def list_all():
""" """
List all scenario directories. List all scenario directories from the user's config directory.
""" """
if not os.path.exists(CONFIG_DIR):
os.makedirs(CONFIG_DIR, exist_ok=True)
return [d for d in os.listdir(CONFIG_DIR) if os.path.isdir(os.path.join(CONFIG_DIR, d))] return [d for d in os.listdir(CONFIG_DIR) if os.path.isdir(os.path.join(CONFIG_DIR, d))]
@staticmethod
def list_premade():
"""
List all pre-made scenario directories.
"""
premade_dir = os.path.join(os.path.dirname(__file__), 'templates')
if not os.path.exists(premade_dir):
return []
return [d for d in os.listdir(premade_dir) if os.path.isdir(os.path.join(premade_dir, d))]
def copy_to_user_scenarios(self):
"""
Copy this scenario (and its assets) to the user's scenarios directory.
This is used when a pre-made scenario is selected and needs to be editable.
"""
try:
import shutil
# Source directory (could be pre-made or user directory)
source_dir = self.get_scenario_dir()
# Destination directory (always user directory)
dest_dir = os.path.join(CONFIG_DIR, self.name)
# If the destination already exists, we don't need to copy
if os.path.exists(dest_dir):
logger.debug(f"User scenario '{self.name}' already exists, skipping copy.")
return True
# Check if source is a pre-made scenario
premade_dir = os.path.join(os.path.dirname(__file__), 'templates', self.name)
if os.path.exists(premade_dir):
source_dir = premade_dir
if os.path.exists(source_dir):
shutil.copytree(source_dir, dest_dir)
logger.info(f"Copied scenario '{self.name}' to user scenarios directory.")
return True
else:
logger.error(f"Source scenario directory not found: {source_dir}")
return False
except Exception as e:
logger.error(f"Failed to copy scenario '{self.name}' to user directory: {e}")
return False
def take_screenshot_with_tkinter(): def take_screenshot_with_tkinter():
""" """
@@ -2067,27 +2132,41 @@ class MainWindow(QtWidgets.QMainWindow):
def delete_scenario(self): def delete_scenario(self):
""" """
Delete the current scenario after confirmation. Delete the current scenario after confirmation.
Only deletes user scenarios - templates are protected.
""" """
if not self.current_scenario: if not self.current_scenario:
return return
name = self.current_scenario.name name = self.current_scenario.name
scenario_dir = self.current_scenario.get_scenario_dir()
# Check if this is trying to delete a template (should never happen but extra protection)
templates_dir = os.path.join(os.path.dirname(__file__), 'templates', name)
if os.path.samefile(scenario_dir, templates_dir) if os.path.exists(templates_dir) else False:
QtWidgets.QMessageBox.warning(
self,
"Cannot Delete Template",
f"Cannot delete template scenario '{name}'. Templates are protected from deletion."
)
return
reply = QtWidgets.QMessageBox.question( reply = QtWidgets.QMessageBox.question(
self, self,
"Delete Scenario", "Delete Scenario",
f"Are you sure you want to delete the scenario '{name}'? This cannot be undone.", f"Are you sure you want to delete the scenario '{name}'? This will delete the entire scenario folder and cannot be undone.",
QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No
) )
if reply == QtWidgets.QMessageBox.StandardButton.Yes: if reply == QtWidgets.QMessageBox.StandardButton.Yes:
try: try:
scenario_dir = self.current_scenario.get_scenario_dir()
if os.path.exists(scenario_dir): if os.path.exists(scenario_dir):
import shutil
shutil.rmtree(scenario_dir) shutil.rmtree(scenario_dir)
logger.info(f"Deleted scenario: {name}") logger.info(f"Deleted scenario folder: {scenario_dir}")
self.current_scenario = None self.current_scenario = None
self.load_scenarios() self.load_scenarios()
except Exception as e: except Exception as e:
logger.error(f"Failed to delete scenario '{name}': {e}") logger.error(f"Failed to delete scenario '{name}': {e}")
QtWidgets.QMessageBox.critical(self, "Delete Error", f"Failed to delete scenario.\n{e}") QtWidgets.QMessageBox.critical(self, "Delete Error", f"Failed to delete scenario folder.\n{e}")
def _log_steps_list(self, idx): def _log_steps_list(self, idx):
""" """
@@ -2267,16 +2346,32 @@ class MainWindow(QtWidgets.QMainWindow):
def load_scenarios(self): def load_scenarios(self):
""" """
Load all scenarios and populate the scenario combo box. Load all scenarios and populate the scenario combo box.
Includes both user scenarios and pre-made scenarios.
""" """
logger.debug('Loading scenarios...') logger.debug('Loading scenarios...')
self.combo.clear() self.combo.clear()
scenarios = Scenario.list_all()
for name in scenarios: # Load user scenarios
self.combo.addItem(name) user_scenarios = Scenario.list_all()
premade_scenarios = Scenario.list_premade()
# Add user scenarios first
for name in user_scenarios:
self.combo.addItem(f"📁 {name}", {'name': name, 'is_premade': False})
# Add separator if both types exist
if user_scenarios and premade_scenarios:
self.combo.insertSeparator(self.combo.count())
# Add pre-made scenarios with a different icon/prefix
for name in premade_scenarios:
# Only add if not already in user scenarios
if name not in user_scenarios:
self.combo.addItem(f"{name} (Template)", {'name': name, 'is_premade': True})
self.refresh_window_list() self.refresh_window_list()
if not scenarios: if not user_scenarios and not premade_scenarios:
choice_dialog = QtWidgets.QMessageBox(self) choice_dialog = QtWidgets.QMessageBox(self)
choice_dialog.setWindowTitle('No Scenarios Found') choice_dialog.setWindowTitle('No Scenarios Found')
choice_dialog.setText('No scenarios found. Would you like to create a new scenario or import one?') choice_dialog.setText('No scenarios found. Would you like to create a new scenario or import one?')
@@ -2291,8 +2386,8 @@ class MainWindow(QtWidgets.QMainWindow):
logger.info(f'Creating new scenario: {name}') logger.info(f'Creating new scenario: {name}')
s = Scenario(name) s = Scenario(name)
s.save() s.save()
self.combo.addItem(name) self.combo.addItem(f"📁 {name}", {'name': name, 'is_premade': False})
self.combo.setCurrentText(name) self.combo.setCurrentIndex(0)
else: else:
self.refresh_lists() self.refresh_lists()
elif clicked == import_btn: elif clicked == import_btn:
@@ -2300,23 +2395,79 @@ class MainWindow(QtWidgets.QMainWindow):
else: else:
self.refresh_lists() self.refresh_lists()
else: else:
# Try to restore last scenario
last_scenario_name = self.read_last_scenario() last_scenario_name = self.read_last_scenario()
if last_scenario_name and last_scenario_name in scenarios: if last_scenario_name:
self.combo.setCurrentText(last_scenario_name) # Look for the scenario in the combo box
for i in range(self.combo.count()):
item_data = self.combo.itemData(i)
if item_data and item_data.get('name') == last_scenario_name:
self.combo.setCurrentIndex(i)
break
else:
# If last scenario not found, select first available
if self.combo.count() > 0:
self.combo.setCurrentIndex(0)
else: else:
self.combo.setCurrentIndex(0) # Select first scenario if available
if self.combo.count() > 0:
self.combo.setCurrentIndex(0)
def select_scenario(self): def select_scenario(self):
""" """
Load the selected scenario and update the UI. Load the selected scenario and update the UI.
Handles both user scenarios and pre-made scenario templates.
""" """
name = self.combo.currentText() current_index = self.combo.currentIndex()
logger.info(f'Scenario selected: {name}') item_data = self.combo.itemData(current_index)
if name:
self.current_scenario = Scenario.load(name) if not item_data:
self.save_last_scenario(name) # Might be a separator or invalid selection
self.refresh_lists() logger.warning("No valid scenario data found for selection")
self.load_selected_window_from_config() return
scenario_name = item_data.get('name')
is_premade = item_data.get('is_premade', False)
logger.info(f'Scenario selected: {scenario_name} ({"pre-made" if is_premade else "user"})')
if scenario_name:
# Load the scenario from appropriate location
self.current_scenario = Scenario.load(scenario_name, from_premade=is_premade)
if self.current_scenario:
# If it's a pre-made scenario, immediately copy it to user folder to protect the template
if is_premade:
logger.info(f"Loaded template scenario '{scenario_name}'. Copying to user scenarios folder for editing.")
success = self.current_scenario.copy_to_user_scenarios()
if success:
# Reload the scenario from the user directory to ensure we're working with the copy
self.current_scenario = Scenario.load(scenario_name, from_premade=False)
# Show a brief tooltip or status message
QtWidgets.QToolTip.showText(
self.combo.mapToGlobal(self.combo.rect().bottomLeft()),
"Template copied to your scenarios folder for editing!",
self.combo,
QtCore.QRect(),
3000 # Show for 3 seconds
)
else:
QtWidgets.QMessageBox.warning(
self,
"Copy Error",
f"Failed to copy template '{scenario_name}' to user scenarios folder. You may not be able to save changes."
)
self.save_last_scenario(scenario_name)
self.refresh_lists()
self.load_selected_window_from_config()
else:
logger.error(f"Failed to load scenario: {scenario_name}")
QtWidgets.QMessageBox.warning(
self,
"Load Error",
f"Failed to load scenario '{scenario_name}'. The scenario file may be corrupted."
)
def create_scenario(self): def create_scenario(self):
""" """
@@ -2328,7 +2479,13 @@ class MainWindow(QtWidgets.QMainWindow):
s = Scenario(name) s = Scenario(name)
s.save() s.save()
self.load_scenarios() self.load_scenarios()
self.combo.setCurrentText(name)
# Find and select the newly created scenario
for i in range(self.combo.count()):
item_data = self.combo.itemData(i)
if item_data and item_data.get('name') == name and not item_data.get('is_premade', False):
self.combo.setCurrentIndex(i)
break
def rename_scenario(self): def rename_scenario(self):
""" """
-16
View File
@@ -1,16 +0,0 @@
{
"name": "dwdw",
"steps": [
{
"name": "1",
"condition": "OR",
"images": [],
"actions": [
{
"type": "delay",
"params": {}
}
]
}
]
}
-15
View File
@@ -1,15 +0,0 @@
{
"name": "iuhgiuo",
"images": [],
"actions": [
{
"type": "click",
"params": {
"delay_before": 0,
"delay_after": 0
},
"image_refs": [],
"logic": "OR"
}
]
}
+74
View File
@@ -0,0 +1,74 @@
{
"name": "Gaming Example",
"steps": [
{
"name": "Attack",
"condition": "OR",
"images": [],
"actions": [
{
"type": "key",
"params": {
"key": "Space"
}
},
{
"type": "delay",
"params": {
"duration": 0.1
}
}
]
},
{
"name": "Use Ability",
"condition": "OR",
"images": [],
"actions": [
{
"type": "key",
"params": {
"key": "1"
}
},
{
"type": "delay",
"params": {
"duration": 2.0
}
}
]
},
{
"name": "Move Character",
"condition": "OR",
"images": [],
"actions": [
{
"type": "key",
"params": {
"key": "W"
}
},
{
"type": "delay",
"params": {
"duration": 0.5
}
},
{
"type": "key",
"params": {
"key": "A"
}
},
{
"type": "delay",
"params": {
"duration": 0.2
}
}
]
}
]
}
@@ -0,0 +1,25 @@
{
"name": "Simple Click Example",
"steps": [
{
"name": "Click on Button",
"condition": "OR",
"images": [],
"actions": [
{
"type": "click",
"params": {
"button": "left",
"pos_type": "center"
}
},
{
"type": "delay",
"params": {
"duration": 1.0
}
}
]
}
]
}
@@ -0,0 +1,63 @@
{
"name": "Web Browser Example",
"steps": [
{
"name": "Refresh Page",
"condition": "OR",
"images": [],
"actions": [
{
"type": "key",
"params": {
"key": "F5"
}
},
{
"type": "delay",
"params": {
"duration": 2.0
}
}
]
},
{
"name": "Scroll Down",
"condition": "OR",
"images": [],
"actions": [
{
"type": "scroll",
"params": {
"direction": "down",
"amount": 300
}
},
{
"type": "delay",
"params": {
"duration": 0.5
}
}
]
},
{
"name": "Go Back",
"condition": "OR",
"images": [],
"actions": [
{
"type": "key",
"params": {
"key": "Alt+Left"
}
},
{
"type": "delay",
"params": {
"duration": 1.0
}
}
]
}
]
}