# NotePlan Plugin Launcher: Technical Deep-Dive ![NotePlan Plugin Launcher Architecture](/assets/technical-architecture.png) ## Application Architecture NotePlan Plugin Launcher is a PyQt6 desktop application that serves as a bridge between users and NotePlan plugins. The architecture follows an MVC pattern with these core components: ### Core Components - **Models**: Data structures and business logic - **Views**: UI components that display data to users - **Controllers**: Logic that connects models and views ## Key Modules ### Data Model (`models.py`) The `PluginStore` class is the central data repository, implemented as a singleton: ```python class PluginStore(QObject): # Signals for UI updates plugins_updated = pyqtSignal() favorites_updated = pyqtSignal() recents_updated = pyqtSignal() @classmethod def get_instance(cls): if cls._instance is None: cls._instance = PluginStore() return cls._instance ``` The data model includes: - **Plugin**: Represents a NotePlan plugin with metadata and commands - **PluginCommand**: Individual commands within a plugin - **RecentCommand**: Recently executed commands with timestamps - **FavoriteCommand**: User's favorite commands with custom display names ### Plugin Discovery The application automatically locates NotePlan's plugins directory, accounting for different installation methods: ```python def _locate_noteplan_plugins_path(self): """Find the NotePlan plugins directory""" from pathlib import Path home = Path.home() # Define potential paths potential_paths = [ # Sandboxed Setapp version home / "Library/Containers/co.noteplan.NotePlan-setapp/Data/Library/Application Support/co.noteplan.NotePlan-setapp/Plugins", # Normal sandboxed version home / "Library/Containers/co.noteplan.NotePlan/Data/Library/Application Support/co.noteplan.NotePlan/Plugins", # Direct non-sandboxed version home / "Library/Application Support/co.noteplan.NotePlan/Plugins", # Older version home / "Library/Application Support/NotePlan/Plugins", ] # Check containers directory for any other NotePlan variants # ... ``` ### User Interface The interface is built with PyQt6 and follows these design principles: 1. **Minimal Footprint**: Fixed height (80px) with adjustable width 2. **Plugin Banner**: Horizontal row of plugin icons with tooltips 3. **Command Lists**: Popup menus for accessing plugin commands 4. **Responsive Design**: Adapts to different window sizes 5. **Theme Support**: Light and dark mode with dynamic switching Key UI classes: - **MainWindow**: Main application window and controller - **BannerView**: Primary UI component that displays plugin icons - **FavoritesView**: UI for managing favorite commands - **RecentView**: UI for displaying recently used commands ### Command Execution The application uses URL schemes to communicate with NotePlan: ```python def execute_command(self, plugin: Plugin, command: PluginCommand, command_key=None): # Construct the URL with proper encoding url = f"noteplan://x-callback-url/runPlugin?pluginID={plugin_id}&command={command_name}" # Platform-specific command execution if platform.system() == "Darwin": # macOS # Launch NotePlan first subprocess.run(["open", "-a", "NotePlan"], check=False) time.sleep(0.3) # Wait for NotePlan to initialize # Then launch the command URL subprocess.run(["open", url], check=False) # Additional fallback methods... ``` ### Data Persistence User preferences and data are stored in JSON files: - **Recent Commands**: Last 20 executed commands - **Favorite Commands**: User-selected favorites with display names - **Plugin Order**: Custom arrangement of plugins in the UI - **Hidden Plugins**: Plugins excluded from the UI ## Technical Challenges ### Cross-Platform Compatibility While primarily designed for macOS, the application has adaptations for other platforms: ```python # Load and set system font based on platform if platform.system() == "Darwin": # macOS default_font = QFont("SF Pro Display", 10) elif platform.system() == "Windows": default_font = QFont("Segoe UI", 10) else: # Linux and others default_font = QFont("Ubuntu", 10) ``` ### NotePlan Integration The application must handle different NotePlan installation scenarios: 1. App Store version (sandboxed) 2. Direct download version (non-sandboxed) 3. Setapp version (different container) ### UI Responsiveness To maintain a fluid experience: - Background plugin scanning to prevent UI freezing - Signal-based updates to propagate changes to all views - Careful error handling to prevent UI crashes ## Project Structure ``` NotePlan-Plugin-Launcher/ ├── app.py # Application entry point ├── models.py # Data models ├── run.sh # Launch script with dependency checks ├── requirements.txt # Python dependencies ├── utils.py # Helper functions └── ui/ # UI components ├── banner_view.py # Main plugin display ├── favorites_view.py # Favorites management ├── main_window.py # Main application window ├── plugin_list.py # Plugin command list ├── plugins_visibility_view.py # Plugin visibility controls └── recent_view.py # Recent commands view ``` ## Performance Considerations - **Memory Usage**: Minimized by loading plugin data on-demand - **Startup Time**: Optimized by caching plugin information - **UI Responsiveness**: Background tasks for data loading operations - **Error Handling**: Graceful recovery from unexpected conditions ## Future Development Areas for potential enhancement: 1. **Plugin Management**: Enable installation/updating of plugins 2. **Command Parameters**: Support for running commands with parameters 3. **Global Hotkeys**: System-wide shortcuts for favorite commands 4. **Custom Theming**: User-configurable appearance settings 5. **Plugin Grouping**: Organize plugins into custom categories --- This application demonstrates how Python and PyQt6 can be used to create efficient desktop utilities that enhance productivity workflows. Buy Me A Coffee