Component Hierarchy
The plasmoid follows a typical Plasma widget structure with these main layers:Core Components
Main Plasmoid (main.qml)
The root component that orchestrates all functionality:
- Type:
PlasmoidItem - Location:
package/contents/ui/main.qml - Responsibilities:
- Manages client connection lifecycle
- Subscribes to entity state updates
- Maintains entity data model (
itemModel) - Handles notifications for entity changes
- Provides context menu actions
url: Home Assistant server URL from configurationitems: Array of configured entities (fromplasmoid.configuration.items)itemModel: ListModel containing live entity dataha: Client instance from ClientFactoryinitialized: Boolean indicating if initial data has loaded
Client Factory (ClientFactory.qml)
- Type: Singleton QML object
- Location:
package/contents/ui/ClientFactory.qml - Purpose: Creates and manages shared Client instances
- Key Features:
- Reuses client instances across consumers with the same URL
- Integrates with KDE Wallet via Secrets component
- Handles component lifecycle and cleanup
- Reports client creation errors
WebSocket Client (Client.qml)
- Type: BaseObject wrapping QtWebSockets.WebSocket
- Location:
package/contents/ui/Client.qml - Purpose: Handles Home Assistant WebSocket API communication
- Features:
- Automatic authentication with token
- Ping/pong keepalive mechanism (30s interval)
- Automatic reconnection on timeout
- Promise-based async API
- Entity subscription management
Representation Components
Compact Representation (CompactRepresentation.qml)
- Location:
package/contents/ui/CompactRepresentation.qml - Purpose: Shows plasmoid icon in system tray or panel
- Behavior: Toggles expanded view on click
- Display: Home Assistant MDI icon
Full Representation (FullRepresentation.qml)
- Location:
package/contents/ui/FullRepresentation.qml - Purpose: Displays entity grid in expanded popup or desktop widget
- Layout: Dynamic grid that adapts to available width
- Features:
- Responsive column count based on width
- Minimum item width:
Kirigami.Units.iconSizes.enormous - Shows status indicator for errors
- Displays placeholder when not configured
- Shows configuration button when required
Entity Delegate Tile (EntityDelegateTile.qml)
- Location:
package/contents/ui/EntityDelegateTile.qml - Purpose: Renders individual entity display
- Layout: 2-column grid with icon and text
- Display Logic:
- Icon: Uses entity icon or MDI icon
- Top-right: Entity value (if available)
- Bottom-right: Entity name
- Bold value text when entity has data
Data Model Components
Entity Model (model.mjs)
- Location:
package/contents/code/model.mjs - Type: JavaScript ES Module
- Exports:
Entity: Runtime entity data with stateConfigEntity: Configuration entity with actionsgetDisplayValue: Value formatting function
Configuration Components
General Configuration (ConfigGeneral.qml)
- Purpose: Configure Home Assistant connection
- Settings:
- Server URL (with autocomplete from saved servers)
- Access token (stored in KDE Wallet)
- Flat entities display option
- Integration: Uses Secrets component for secure token storage
Items Configuration (ConfigItems.qml)
- Purpose: Manage displayed entities
- Features:
- Add/edit/delete entities
- Reorder with drag handles
- Import/export entity configuration
- Auto-backup to file
- Live entity data from Home Assistant
Item Configuration (ConfigItem.qml)
- Purpose: Edit individual entity settings
- Fields:
- Entity ID (with autocomplete)
- Display attribute selector
- Custom name and icon
- Notification on change
- Click action (service call)
- Scroll action (for number fields)
Component Communication Flow
Initialization Flow
main.qmlloads and reads configurationClientFactory.getClient()creates or retrieves Client instance- Client connects WebSocket to Home Assistant
- Client authenticates with token from Secrets
main.qmlsubscribes to configured entities- Initial entity states populate
itemModel FullRepresentationdisplays entity grid
State Update Flow
- Home Assistant sends state change event
- Client receives WebSocket message
- Client calls subscription callback with event data
main.qml.processData()updatesitemModel- Entity model creates new
Entityinstance - UI automatically updates via model binding
- Notification shown if entity has
notifyenabled
Service Call Flow
- User interacts with entity tile (click/scroll)
- Entity component calls
root.ha.callService() - Client sends WebSocket command with promise
- Home Assistant executes service
- Client receives result and resolves promise
- State update follows normal update flow
Helper Components
Thecomponents/ directory contains reusable utilities:
- BaseObject: Base QML object with common properties
- DynamicIcon: Renders MDI or Plasma icons
- MdiIcon: Material Design Icons renderer
- Notifications: KDE notification integration
- Secrets: KDE Wallet integration for token storage
- StatusIndicator: Error indicator overlay
- File: File dialog wrapper
- Autocompletion: TextField autocomplete popup
Threading and Async Operations
The plasmoid uses JavaScript Promises for asynchronous operations:- WebSocket commands: All API calls return promises
- Token retrieval: Secrets component uses promises
- Service calls:
callService(),getServices(),getStates()are async
Error Handling
Error handling occurs at multiple levels:- Client Component: Emits
errorsignal with message string - Main Plasmoid: Sets
errorStringproperty - UI: StatusIndicator shows error overlay
- Configuration: InlineMessage displays connection errors
- ClientFactory: Reports QML component creation errors
Performance Considerations
- Shared Clients: ClientFactory ensures one client per URL
- Lazy Loading: FullRepresentation grid loads only when initialized
- Efficient Updates: Only changed entities update model
- Filtered Subscriptions: Only configured entities are subscribed
- Keepalive: 30-second ping/pong prevents unnecessary reconnections
Next Steps
- Client API Reference - Detailed WebSocket client documentation
- Entity Model - Entity data structures
- UI Components - Visual component documentation
