Files
DBClient/app/ui/preferences_dialog.py
T
nngoandClaude Sonnet 4.6 771c92b7b6 feat: preferences dialog, SQL formatter, and enhanced table context menu
- PreferencesDialog (Tools → Preferences, Ctrl+,): font family/size,
  word wrap, default page size, query timeout, max history, auto-commit;
  font changes apply live to all open editors via apply_settings() cascade
- CodeEditor and TableViewer now read initial values from settings singleton
- SQL formatter (≡ Format button): uses sqlparse to reindent and uppercase
  keywords; gracefully prompts to install sqlparse if missing
- Table viewer context menu: "Filter by this value" (populates WHERE and
  reloads), "Copy row as SQL INSERT" (ready-to-paste INSERT statements),
  renamed "Copy row" → "Copy row as TSV" for clarity

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 17:05:54 -04:00

134 lines
5.1 KiB
Python

"""Application Preferences dialog."""
from PyQt6.QtWidgets import (
QDialog, QVBoxLayout, QFormLayout, QGroupBox,
QComboBox, QSpinBox, QCheckBox, QDialogButtonBox, QLabel,
)
from PyQt6.QtCore import pyqtSignal
from app.config.settings import get_settings
_FONT_FAMILIES = ["Consolas", "JetBrains Mono", "Fira Code", "Cascadia Code", "Courier New"]
_PAGE_SIZES = [50, 100, 500, 1000, 0] # 0 → All
_PAGE_LABELS = ["50", "100", "500", "1 000", "All"]
class PreferencesDialog(QDialog):
settings_applied = pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("Preferences")
self.setMinimumWidth(400)
self.resize(420, 380)
self._build_ui()
self._load()
def _build_ui(self):
root = QVBoxLayout(self)
root.setSpacing(12)
root.setContentsMargins(16, 16, 16, 16)
# ── SQL Editor ────────────────────────────────────────────────────────
editor_box = QGroupBox("SQL Editor")
ef = QFormLayout(editor_box)
ef.setSpacing(8)
self._font_family = QComboBox()
self._font_family.addItems(_FONT_FAMILIES)
ef.addRow("Font family:", self._font_family)
self._font_size = QSpinBox()
self._font_size.setRange(8, 28)
self._font_size.setSuffix(" pt")
ef.addRow("Font size:", self._font_size)
self._word_wrap = QCheckBox("Word wrap")
ef.addRow("", self._word_wrap)
root.addWidget(editor_box)
# ── Results ───────────────────────────────────────────────────────────
results_box = QGroupBox("Results")
rf = QFormLayout(results_box)
rf.setSpacing(8)
self._page_size = QComboBox()
for lbl in _PAGE_LABELS:
self._page_size.addItem(lbl)
rf.addRow("Default page size:", self._page_size)
self._timeout = QSpinBox()
self._timeout.setRange(5, 600)
self._timeout.setSuffix(" s")
rf.addRow("Query timeout:", self._timeout)
root.addWidget(results_box)
# ── General ───────────────────────────────────────────────────────────
general_box = QGroupBox("General")
gf = QFormLayout(general_box)
gf.setSpacing(8)
self._max_history = QSpinBox()
self._max_history.setRange(50, 10_000)
self._max_history.setSingleStep(100)
gf.addRow("Max history entries:", self._max_history)
self._auto_commit = QCheckBox("Auto-commit queries")
gf.addRow("", self._auto_commit)
root.addWidget(general_box)
root.addStretch()
# ── Buttons ───────────────────────────────────────────────────────────
note = QLabel("Font changes take effect immediately in open editors.")
note.setObjectName("statusLabel")
root.addWidget(note)
bb = QDialogButtonBox(
QDialogButtonBox.StandardButton.Cancel |
QDialogButtonBox.StandardButton.Apply |
QDialogButtonBox.StandardButton.Ok
)
bb.rejected.connect(self.reject)
bb.button(QDialogButtonBox.StandardButton.Apply).clicked.connect(self._apply)
bb.accepted.connect(self._ok)
root.addWidget(bb)
# ── Load / save ───────────────────────────────────────────────────────────
def _load(self):
s = get_settings()
family = s.get("font_family", "Consolas")
idx = self._font_family.findText(family)
self._font_family.setCurrentIndex(max(idx, 0))
self._font_size.setValue(s.get("font_size", 13))
self._word_wrap.setChecked(s.get("word_wrap", False))
page = s.get("result_page_size", 100)
pi = _PAGE_SIZES.index(page) if page in _PAGE_SIZES else 1
self._page_size.setCurrentIndex(pi)
self._timeout.setValue(s.get("query_timeout", 60))
self._max_history.setValue(s.get("max_history", 500))
self._auto_commit.setChecked(s.get("auto_commit", True))
def _apply(self):
s = get_settings()
s.set("font_family", self._font_family.currentText())
s.set("font_size", self._font_size.value())
s.set("word_wrap", self._word_wrap.isChecked())
s.set("result_page_size", _PAGE_SIZES[self._page_size.currentIndex()])
s.set("query_timeout", self._timeout.value())
s.set("max_history", self._max_history.value())
s.set("auto_commit", self._auto_commit.isChecked())
s.save()
self.settings_applied.emit()
def _ok(self):
self._apply()
self.accept()