AI-first API testing desktop client built with Python + PyQt6. Features: - Multi-tab HTTP request editor with params/headers/body/auth/tests - KeyValueTable with per-row enable/disable checkboxes and 36px rows - Format JSON button, syntax highlighting, pre-request & test scripts - Collections, environments, history, import/export (Postman v2.1, cURL) - OpenAPI 3.x / Swagger 2.0 local parser (no AI tokens) - EKIKA Odoo API Framework generator — JSON-API, REST JSON, GraphQL, Custom REST JSON with all auth types (instant, no AI tokens) - Persistent AI chat sidebar (Claude-powered co-pilot) with streaming, context-aware suggestions, and one-click Apply to request editor - AI collection generator from any docs URL or pasted spec - WebSocket client, Mock server, Collection runner, Code generator - Dark/light theme engine (global QSS, object-name selectors) - SSL error detection with actionable hints - MIT License Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
77 lines
2.5 KiB
Python
77 lines
2.5 KiB
Python
"""APIClient - Agent — Code Generation Dialog."""
|
|
from PyQt6.QtWidgets import (
|
|
QDialog, QVBoxLayout, QHBoxLayout, QComboBox,
|
|
QTextEdit, QPushButton, QLabel, QApplication, QWidget
|
|
)
|
|
from PyQt6.QtGui import QFont
|
|
from app.ui.theme import Colors
|
|
from app.core.code_gen import GENERATORS
|
|
from app.models import HttpRequest
|
|
|
|
|
|
class CodeGenDialog(QDialog):
|
|
def __init__(self, req: HttpRequest, parent=None):
|
|
super().__init__(parent)
|
|
self.req = req
|
|
self.setWindowTitle("Generate Code Snippet")
|
|
self.setMinimumSize(720, 540)
|
|
|
|
layout = QVBoxLayout(self)
|
|
layout.setContentsMargins(0, 0, 0, 0)
|
|
layout.setSpacing(0)
|
|
|
|
# Header
|
|
header = QWidget()
|
|
header.setObjectName("panelHeader")
|
|
header.setFixedHeight(52)
|
|
hl = QHBoxLayout(header)
|
|
hl.setContentsMargins(16, 0, 16, 0)
|
|
title = QLabel("Generate Code")
|
|
title.setObjectName("panelTitle")
|
|
hl.addWidget(title)
|
|
hl.addStretch()
|
|
lang_label = QLabel("Language:")
|
|
lang_label.setObjectName("fieldLabel")
|
|
self.lang_combo = QComboBox()
|
|
self.lang_combo.addItems(list(GENERATORS.keys()))
|
|
self.lang_combo.setMinimumWidth(200)
|
|
self.lang_combo.currentTextChanged.connect(self._generate)
|
|
hl.addWidget(lang_label)
|
|
hl.addWidget(self.lang_combo)
|
|
layout.addWidget(header)
|
|
|
|
# Code view
|
|
self.code_view = QTextEdit()
|
|
self.code_view.setObjectName("codeEditor")
|
|
self.code_view.setReadOnly(True)
|
|
self.code_view.setFont(QFont("JetBrains Mono, Fira Code, Cascadia Code, Consolas", 11))
|
|
layout.addWidget(self.code_view, 1)
|
|
|
|
# Footer
|
|
footer = QWidget()
|
|
footer.setObjectName("panelFooter")
|
|
footer.setFixedHeight(52)
|
|
fl = QHBoxLayout(footer)
|
|
fl.setContentsMargins(16, 0, 16, 0)
|
|
fl.addStretch()
|
|
copy_btn = QPushButton("Copy to Clipboard")
|
|
copy_btn.setObjectName("accent")
|
|
copy_btn.setFixedWidth(150)
|
|
copy_btn.clicked.connect(self._copy)
|
|
close_btn = QPushButton("Close")
|
|
close_btn.setFixedWidth(80)
|
|
close_btn.clicked.connect(self.accept)
|
|
fl.addWidget(copy_btn)
|
|
fl.addWidget(close_btn)
|
|
layout.addWidget(footer)
|
|
|
|
self._generate(self.lang_combo.currentText())
|
|
|
|
def _generate(self, lang: str):
|
|
gen = GENERATORS.get(lang)
|
|
if gen:
|
|
self.code_view.setPlainText(gen(self.req))
|
|
|
|
def _copy(self):
|
|
QApplication.clipboard().setText(self.code_view.toPlainText())
|