120 lines
3.0 KiB
TypeScript
120 lines
3.0 KiB
TypeScript
import { ref, onMounted } from 'vue'
|
|
|
|
declare global {
|
|
interface Window {
|
|
QWebChannel?: typeof QWebChannel
|
|
qt?: {
|
|
webChannelTransport?: any
|
|
}
|
|
}
|
|
|
|
const QWebChannel: {
|
|
new(transport: any, ready: (channel: any) => void): void
|
|
}
|
|
}
|
|
|
|
interface PythonEvent {
|
|
type: string
|
|
data: any
|
|
}
|
|
|
|
const pyjs = ref<any>(null)
|
|
const isReady = ref<boolean>(false)
|
|
|
|
// Хранилище обработчиков событий
|
|
const pythonEventHandlers = new Map<string, Array<(data: any) => void>>()
|
|
|
|
function receiveFromPython(eventType: string, data: any) {
|
|
console.warn("🟢 Событие из Python:", eventType, data)
|
|
|
|
const handlers = pythonEventHandlers.get(eventType) || []
|
|
handlers.forEach(handler => handler(data))
|
|
}
|
|
|
|
export function usePythonBridge() {
|
|
function setupQWebChannel() {
|
|
if (window.QWebChannel && window.qt && window.qt.webChannelTransport) {
|
|
new window.QWebChannel(window.qt.webChannelTransport, function (channel) {
|
|
isReady.value = true
|
|
pyjs.value = channel.objects.pyjs
|
|
|
|
// Получаем доступ к эмиттеру событий
|
|
const eventEmitter = channel.objects.pyjs_events
|
|
|
|
// Подписываемся на событие один раз
|
|
if (eventEmitter && eventEmitter.onEvent) {
|
|
eventEmitter.onEvent.connect(receiveFromPython)
|
|
}
|
|
})
|
|
} else {
|
|
console.error('Qt WebChannel недоступен')
|
|
}
|
|
}
|
|
|
|
async function sendCommandToPython<T = any>(
|
|
command: string,
|
|
data: Record<string, any> = {}
|
|
): Promise<T> {
|
|
return new Promise((resolve, reject) => {
|
|
if (!isReady.value) {
|
|
reject(new Error('Мост еще не готов'))
|
|
return
|
|
}
|
|
|
|
if (!pyjs.value || !pyjs.value.callFromJS) {
|
|
reject(new Error('Python недоступен'))
|
|
return
|
|
}
|
|
|
|
pyjs.value.callFromJS(command, JSON.stringify(data), (result: string) => {
|
|
try {
|
|
resolve(JSON.parse(result))
|
|
} catch (e) {
|
|
reject(e)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// Регистрация обработчика событий по типу
|
|
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 (window.QWebChannel && window.qt?.webChannelTransport) {
|
|
setupQWebChannel()
|
|
}
|
|
|
|
if (pyjs.value) {
|
|
console.warn('✅ pyjs готов')
|
|
} else {
|
|
setTimeout(checkBridge, 500)
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
checkBridge()
|
|
})
|
|
|
|
return {
|
|
isReady,
|
|
sendCommandToPython,
|
|
onPythonEvent,
|
|
offPythonEvent,
|
|
}
|
|
} |