// composables/usePythonBridge.ts declare global { interface Window { QWebChannel?: typeof QWebChannel qt?: { webChannelTransport?: any } } const QWebChannel: { new(transport: any, ready: (channel: any) => void): void } } export function usePythonBridge() { const pyjs = useState('bridge_pyjs', () => null) const isReady = useState('bridge_ready', () => false) const isAvailableOnPlatform = useState('bridge_av', () => false) const loading = useState('bridge_loading', () => false) // Хранилище обработчиков событий const pythonEventHandlers = new Map void>>() function receiveFromPython(eventType: string, data: any) { console.warn("🟢 Event from Python:", eventType, data) const handlers = pythonEventHandlers.get(eventType) || [] handlers.forEach(handler => handler(data)) } function setupQWebChannel() { if (window.QWebChannel && window.qt && window.qt.webChannelTransport) { new window.QWebChannel(window.qt.webChannelTransport, function (channel) { isAvailableOnPlatform.value = true isReady.value = true pyjs.value = channel.objects.pyjs // Получаем доступ к эмиттеру событий const eventEmitter = channel.objects.pyjs_events // Подписываемся на событие один раз if (eventEmitter && eventEmitter.onEvent) { eventEmitter.onEvent.connect(receiveFromPython) } }) } else { isAvailableOnPlatform.value = false console.error('Qt WebChannel недоступен') } } async function sendCommandToPython( command: string, data: Record = {} ): Promise { if (!isReady.value) { throw new Error('Мост еще не готов') } if (!pyjs.value || !pyjs.value.callFromJS) { throw new Error('Python недоступен') } loading.value = true return new Promise((resolve, reject) => { setTimeout(() => { try { pyjs.value.callFromJS(command, JSON.stringify(data), (result: string) => { try { const parsed = JSON.parse(result) resolve(parsed) } catch (e) { reject(e) } finally { loading.value = false } }) } catch (err) { reject(err) loading.value = false } }, 300) }) } // Регистрация обработчика событий по типу function onPythonEvent(eventType: string, handler: (data: any) => void) { if (!pythonEventHandlers.has(eventType)) { pythonEventHandlers.set(eventType, []) } pythonEventHandlers.get(eventType)?.push(handler) } // Отписка от события function offPythonEvent(eventType: string, handler: (data: any) => void) { const handlers = pythonEventHandlers.get(eventType) if (handlers) { const index = handlers.indexOf(handler) if (index > -1) { handlers.splice(index, 1) } } } const checkBridge = () => { if (import.meta.client && window.QWebChannel && window.qt?.webChannelTransport) { setupQWebChannel() } if (pyjs.value) { console.warn('✅ pyjs готов') } else { setTimeout(checkBridge, 500) } } // Вызываем один раз при первом монтировании if (!isReady.value) { checkBridge() } return { pyjs, isReady, isAvailableOnPlatform, loading, sendCommandToPython, onPythonEvent, offPythonEvent, } }