UI Enhancements.

This commit is contained in:
2026-03-28 18:01:49 +05:30
parent 79b120ff91
commit a90e3a0d84
15 changed files with 292 additions and 58 deletions

View File

@@ -1,20 +1,23 @@
"""APIClient - Agent - Main Window."""
import os
from PyQt6.QtWidgets import (
QMainWindow, QSplitter, QWidget, QVBoxLayout, QHBoxLayout,
QLabel, QComboBox, QPushButton, QStatusBar, QTabWidget,
QInputDialog, QMessageBox, QFileDialog, QApplication
)
from PyQt6.QtCore import Qt, QThread, pyqtSignal
from PyQt6.QtGui import QKeySequence, QShortcut
from PyQt6.QtGui import QKeySequence, QShortcut, QPixmap
from app.ui.tabs_manager import TabsManager
from app.ui.response_panel import ResponsePanel
from app.ui.sidebar import CollectionsSidebar
from app.ui.theme import Colors, toggle as toggle_theme, is_dark
from app.ui.theme import Colors, toggle as toggle_theme, is_dark, zoom_in, zoom_out, zoom_reset, get_zoom
from app.core import http_client, storage
from app.core.test_runner import run_tests
from app.models import HttpRequest
_ASSETS_DIR = os.path.join(os.path.dirname(__file__), "..", "..", "assets")
APP_VERSION = "2.0.0"
APP_NAME = "APIClient - Agent"
@@ -50,22 +53,62 @@ class EnvBar(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setObjectName("envBar")
self.setFixedHeight(46)
self.setFixedHeight(48)
layout = QHBoxLayout(self)
layout.setContentsMargins(16, 0, 16, 0)
layout.setContentsMargins(12, 0, 12, 0)
layout.setSpacing(6)
# EKIKA logo
logo_path = os.path.join(_ASSETS_DIR, "ekika_logo.png")
if os.path.exists(logo_path):
logo_lbl = QLabel()
logo_lbl.setObjectName("ekikaLogo")
pix = QPixmap(logo_path)
logo_lbl.setPixmap(pix.scaledToHeight(26, Qt.TransformationMode.SmoothTransformation))
logo_lbl.setToolTip("EKIKA")
layout.addWidget(logo_lbl)
# Thin separator
sep = QLabel("|")
sep.setObjectName("brandSub")
sep.setFixedWidth(12)
sep.setAlignment(Qt.AlignmentFlag.AlignCenter)
layout.addWidget(sep)
brand = QLabel("APIClient")
brand.setObjectName("brandName")
sub = QLabel("Agent")
sub = QLabel("- Agent")
sub.setObjectName("brandSub")
layout.addWidget(brand)
layout.addWidget(sub)
layout.addStretch()
# Zoom controls
zoom_out_btn = QPushButton("-")
zoom_out_btn.setObjectName("zoomBtn")
zoom_out_btn.setFixedSize(24, 24)
zoom_out_btn.setToolTip("Zoom Out (Ctrl+-)")
layout.addWidget(zoom_out_btn)
self.zoom_out_btn = zoom_out_btn
self.zoom_label = QLabel("100%")
self.zoom_label.setObjectName("zoomLabel")
self.zoom_label.setFixedWidth(42)
self.zoom_label.setToolTip("Current zoom level (Ctrl+0 to reset)")
layout.addWidget(self.zoom_label)
zoom_in_btn = QPushButton("+")
zoom_in_btn.setObjectName("zoomBtn")
zoom_in_btn.setFixedSize(24, 24)
zoom_in_btn.setToolTip("Zoom In (Ctrl+=)")
layout.addWidget(zoom_in_btn)
self.zoom_in_btn = zoom_in_btn
# Thin gap
layout.addSpacing(8)
env_label = QLabel("ENV")
env_label.setObjectName("envChip")
layout.addWidget(env_label)
@@ -119,6 +162,8 @@ class MainWindow(QMainWindow):
self.env_bar.manage_btn.clicked.connect(self._open_env_dialog)
self.env_bar.theme_btn.clicked.connect(self._toggle_theme)
self.env_bar.ai_btn.clicked.connect(self._toggle_ai_chat)
self.env_bar.zoom_in_btn.clicked.connect(self._zoom_in)
self.env_bar.zoom_out_btn.clicked.connect(self._zoom_out)
root_layout.addWidget(self.env_bar)
splitter = QSplitter(Qt.Orientation.Horizontal)
@@ -203,6 +248,10 @@ class MainWindow(QMainWindow):
view_m = mb.addMenu("View")
view_m.addAction("Search Requests", self._open_search).setShortcut("Ctrl+F")
view_m.addAction("Toggle Theme", self._toggle_theme)
view_m.addSeparator()
view_m.addAction("Zoom In", self._zoom_in).setShortcut("Ctrl+=")
view_m.addAction("Zoom Out", self._zoom_out).setShortcut("Ctrl+-")
view_m.addAction("Reset Zoom", self._zoom_reset).setShortcut("Ctrl+0")
tools_m = mb.addMenu("Tools")
tools_m.addAction("Environments…", self._open_env_dialog).setShortcut("Ctrl+E")
@@ -227,10 +276,14 @@ class MainWindow(QMainWindow):
QShortcut(QKeySequence("Ctrl+W"), self, self.tabs_manager.close_current_tab)
QShortcut(QKeySequence("Ctrl+S"), self, self._save_to_collection)
QShortcut(QKeySequence("Ctrl+F"), self, self._open_search)
QShortcut(QKeySequence("Ctrl+E"), self, self._open_env_dialog)
QShortcut(QKeySequence("Ctrl+Shift+A"), self, self._toggle_ai_chat)
QShortcut(QKeySequence("Ctrl+E"), self, self._open_env_dialog)
QShortcut(QKeySequence("Ctrl+Shift+A"), self, self._toggle_ai_chat)
QShortcut(QKeySequence("Escape"), self, self._cancel_request)
QShortcut(QKeySequence("Ctrl+Q"), self, self.close)
QShortcut(QKeySequence("Ctrl+="), self, self._zoom_in)
QShortcut(QKeySequence("Ctrl++"), self, self._zoom_in)
QShortcut(QKeySequence("Ctrl+-"), self, self._zoom_out)
QShortcut(QKeySequence("Ctrl+0"), self, self._zoom_reset)
# ── Environment ───────────────────────────────────────────────────────────
@@ -443,6 +496,23 @@ class MainWindow(QMainWindow):
elif atype == "test":
rp.apply_test_script(content)
# ── Zoom ──────────────────────────────────────────────────────────────────
def _zoom_in(self):
level = zoom_in(QApplication.instance())
self._update_zoom_label(level)
def _zoom_out(self):
level = zoom_out(QApplication.instance())
self._update_zoom_label(level)
def _zoom_reset(self):
level = zoom_reset(QApplication.instance())
self._update_zoom_label(level)
def _update_zoom_label(self, level: float):
self.env_bar.zoom_label.setText(f"{round(level * 100)}%")
# ── Theme ─────────────────────────────────────────────────────────────────
def _toggle_theme(self):