#!/usr/bin/env python3 """ I2C Control Widget - Integrated ================================ Command table (left) + I2C core widget (right) Author: Kynsight Version: 3.0.0 """ from PyQt6.QtWidgets import QWidget, QHBoxLayout, QSplitter from PyQt6.QtCore import Qt, pyqtSignal from command_table.command_table import CommandTableWidget from i2c.i2c_kit.i2c_core_widget import I2CWidget class I2CControlWidget(QWidget): """ Integrated I2C control widget. Layout: Command table (left) | I2C core (right) Signals: command_sent: (command_id, operation, register) reading_received: (reading_info) connection_changed: (is_connected) """ command_sent = pyqtSignal(int, str, str) # command_id, operation, register reading_received = pyqtSignal(object) connection_changed = pyqtSignal(bool) def __init__(self, db_connection, parent=None): super().__init__(parent) self.conn = db_connection self._init_ui() self._setup_connections() def _init_ui(self): """Initialize UI - side by side layout.""" layout = QHBoxLayout() self.setLayout(layout) # Splitter for resizable layout splitter = QSplitter(Qt.Orientation.Horizontal) # Left: Command table self.command_table = CommandTableWidget(self.conn, 'i2c') splitter.addWidget(self.command_table) # Right: I2C core widget self.i2c_core = I2CWidget() splitter.addWidget(self.i2c_core) # Set initial sizes (40% table, 60% core) splitter.setSizes([400, 600]) layout.addWidget(splitter) # Initialize buses on startup self.i2c_core._refresh_buses() # Table always enabled, CRUD buttons disabled initially (not connected) self._update_table_mode(False) def _setup_connections(self): """Connect signals between table and core.""" # Command table → Execute via I2C (when connected) OR Edit (when disconnected) self.command_table.command_double_clicked.connect(self._on_command_double_click) # I2C connection → Change table mode self.i2c_core.connection_changed.connect(self._on_connection_changed) # Forward I2C signals self.i2c_core.reading_received.connect(self.reading_received.emit) def _update_table_mode(self, is_connected): """Update table mode based on connection state.""" if is_connected: # Connected mode: CRUD buttons disabled, double-click executes self.command_table.btn_add.setEnabled(False) self.command_table.btn_edit.setEnabled(False) self.command_table.btn_delete.setEnabled(False) else: # Disconnected mode: CRUD buttons enabled, double-click edits self.command_table.btn_add.setEnabled(True) # Edit/Delete enabled only if something selected has_selection = bool(self.command_table.table.selectedItems()) self.command_table.btn_edit.setEnabled(has_selection) self.command_table.btn_delete.setEnabled(has_selection) def _on_command_double_click(self, command_id, cmd_data): """Handle double-click: Execute if connected, Edit if disconnected.""" if self.i2c_core.is_connected: # Connected: Execute command self._execute_command(command_id, cmd_data) else: # Disconnected: Edit command self.command_table._edit_command() def _execute_command(self, command_id, cmd_data): """Execute I2C command.""" operation = cmd_data.get('operation', '') register = cmd_data.get('register', '') hex_string = cmd_data.get('hex_string', '') device_address = cmd_data.get('device_address', '0x40') if not operation or not register: return try: # Remove 0x prefix if present for consistency device_addr_clean = device_address.replace('0x', '').replace('0X', '') register_clean = register.replace('0x', '').replace('0X', '') # Populate manual I/O fields (correct field names from i2c_core_widget) self.i2c_core.edit_io_addr.setText(device_addr_clean) self.i2c_core.edit_io_reg.setText(register_clean) if operation == 'read': # Determine bytes to read if 'Angle' in cmd_data.get('command_name', ''): num_bytes = 2 elif 'Magnitude' in cmd_data.get('command_name', ''): num_bytes = 2 else: num_bytes = 1 # Set length self.i2c_core.spin_io_length.setValue(num_bytes) # Trigger read (use the button's method) self.i2c_core._on_read() else: # write # Parse data value and set write data field if hex_string: data_clean = hex_string.replace('0x', '').replace('0X', '') self.i2c_core.edit_write_data.setText(data_clean) # Trigger write self.i2c_core._on_write() # Emit signal self.command_sent.emit(command_id, operation, register) except Exception as e: print(f"I2C execute error: {e}") def _on_connection_changed(self, is_connected): """Handle connection state change.""" # Update table mode (CRUD buttons, double-click behavior) self._update_table_mode(is_connected) # Forward signal self.connection_changed.emit(is_connected) def get_i2c_core(self): """Get I2C core widget for direct access.""" return self.i2c_core def get_command_table(self): """Get command table for direct access.""" return self.command_table if __name__ == "__main__": import sys from PyQt6.QtWidgets import QApplication import sqlite3 app = QApplication(sys.argv) conn = sqlite3.connect("./database/ehinge.db") widget = I2CControlWidget(conn) widget.setWindowTitle("I2C Control - Integrated") widget.resize(1400, 800) widget.show() sys.exit(app.exec())