feat: SQL auto-complete, Find/Replace bar, and connection tab coloring

- Add SqlCompleter (sql_completer.py): schema-aware popup with keyword,
  table, view, and lazy column completions; dot-notation and Ctrl+Space
- Add FindBar to EditorTab: inline find/replace with wrap-around,
  case/whole-word flags, match count, and Ctrl+F / Ctrl+H shortcuts
- Color workspace tab text by connection profile in MainWindow
- Move Toggle History shortcut Ctrl+H → Ctrl+Shift+H to free Ctrl+H
  for Find & Replace

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-21 16:42:18 -04:00
co-authored by Claude Sonnet 4.6
parent f680bfe3a3
commit 22f1dd5f45
2 changed files with 235 additions and 8 deletions
+21 -3
View File
@@ -14,7 +14,7 @@ from PyQt6.QtWidgets import (
QPushButton, QApplication,
)
from PyQt6.QtCore import Qt, QTimer
from PyQt6.QtGui import QAction, QKeySequence
from PyQt6.QtGui import QAction, QColor, QKeySequence
from app.ui.schema_browser import SchemaBrowser
from app.ui.sql_editor import SQLEditorWidget
@@ -159,7 +159,7 @@ class MainWindow(QMainWindow):
file_menu.addAction(self._act("Exit", QApplication.quit, "Ctrl+Q"))
view_menu = mb.addMenu("&View")
view_menu.addAction(self._act("Toggle Query History", self._toggle_history, "Ctrl+H"))
view_menu.addAction(self._act("Toggle Query History", self._toggle_history, "Ctrl+Shift+H"))
view_menu.addAction(self._act("New SQL Tab", self._new_sql_tab, "Ctrl+T"))
tools_menu = mb.addMenu("&Tools")
@@ -327,17 +327,30 @@ class MainWindow(QMainWindow):
self._empty_label.setVisible(False)
self._workspace.setVisible(True)
def _profile_for_driver(self, driver):
for pid, d in self._active_drivers.items():
if d is driver:
return self._all_profiles.get(pid)
return None
def _apply_tab_color(self, idx: int, driver) -> None:
profile = self._profile_for_driver(driver)
if profile:
self._workspace.tabBar().setTabTextColor(idx, QColor(profile.color))
def _open_table_viewer(self, driver, database: str, table: str):
tab = TableViewer(driver, database, table)
tab.status_message.connect(self._set_status)
idx = self._workspace.addTab(tab, f"📋 {table}")
self._workspace.setCurrentIndex(idx)
self._apply_tab_color(idx, driver)
def _open_table_structure(self, driver, database: str, table: str):
tab = TableStructureView(driver, database, table)
tab.status_message.connect(self._set_status)
idx = self._workspace.addTab(tab, f"🏗️ {table}")
self._workspace.setCurrentIndex(idx)
self._apply_tab_color(idx, driver)
def _open_sql_editor(self, driver, database: str):
sql_widget = SQLEditorWidget()
@@ -346,6 +359,7 @@ class MainWindow(QMainWindow):
label = f"✏️ SQL — {database}" if database else "✏️ SQL"
idx = self._workspace.addTab(sql_widget, label)
self._workspace.setCurrentIndex(idx)
self._apply_tab_color(idx, driver)
def _new_sql_tab(self):
sql_widget = SQLEditorWidget()
@@ -386,9 +400,12 @@ class MainWindow(QMainWindow):
QMessageBox.information(self, "Keyboard Shortcuts",
"F5 / Ctrl+Enter — Run query\n"
"Ctrl+/ — Toggle comment\n"
"Ctrl+Space — Force auto-complete\n"
"Ctrl+F — Find in SQL editor\n"
"Ctrl+H — Find & Replace in SQL editor\n"
"Ctrl+N — New connection\n"
"Ctrl+T — New SQL tab\n"
"Ctrl+H — Toggle query history\n"
"Ctrl+Shift+H — Toggle query history\n"
"Ctrl+U — User management\n"
"Ctrl+L — View app logs\n"
"Delete — Delete selected row (table viewer)\n"
@@ -411,6 +428,7 @@ class MainWindow(QMainWindow):
panel.status_message.connect(self._set_status)
idx = self._workspace.addTab(panel, f"⚙️ Processes — {name}")
self._workspace.setCurrentIndex(idx)
self._apply_tab_color(idx, driver)
self._show_workspace()
def _open_import_dialog(self):