theme: upgrade palette from Catppuccin Mocha to Frappé

Replaces all dark-Mocha colours (#1e1e2e base, #313244 surface0, etc.)
with the noticeably brighter Frappé variants (#303446 base, #414559
surface0, etc.) across the QSS and every hardcoded colour in Python
source files (syntax highlighter, completer popup, log viewer, explain
view, table viewer, schema browser, icons, etc.).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-21 16:51:37 -04:00
co-authored by Claude Sonnet 4.6
parent 22f1dd5f45
commit b003976d39
14 changed files with 221 additions and 221 deletions
+2 -2
View File
@@ -14,7 +14,7 @@ class ConnectionProfile:
database: str = "" database: str = ""
username: str = "" username: str = ""
password: str = field(default="", repr=False) password: str = field(default="", repr=False)
color: str = "#89b4fa" color: str = "#8caaee"
id: str = field(default_factory=lambda: str(uuid.uuid4())) id: str = field(default_factory=lambda: str(uuid.uuid4()))
ssl: bool = False ssl: bool = False
ssl_cert: str = "" ssl_cert: str = ""
@@ -71,7 +71,7 @@ class ConnectionProfile:
port=data.get("port", 3306), port=data.get("port", 3306),
database=data.get("database", ""), database=data.get("database", ""),
username=data.get("username", ""), username=data.get("username", ""),
color=data.get("color", "#89b4fa"), color=data.get("color", "#8caaee"),
ssl=data.get("ssl", False), ssl=data.get("ssl", False),
ssl_cert=data.get("ssl_cert", ""), ssl_cert=data.get("ssl_cert", ""),
ssl_key=data.get("ssl_key", ""), ssl_key=data.get("ssl_key", ""),
+1 -1
View File
@@ -11,7 +11,7 @@ from PyQt6.QtGui import QColor, QFont
class ResultTableModel(QAbstractTableModel): class ResultTableModel(QAbstractTableModel):
"""Immutable result-set model — replaces data via set_data().""" """Immutable result-set model — replaces data via set_data()."""
NULL_COLOR = QColor("#6c7086") # muted grey for NULL NULL_COLOR = QColor("#737994") # muted grey for NULL
NUM_ALIGN = Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter NUM_ALIGN = Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter
TEXT_ALIGN = Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter TEXT_ALIGN = Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter
+2 -2
View File
@@ -17,7 +17,7 @@ from app.config.connections import save_profile
class ColorButton(QPushButton): class ColorButton(QPushButton):
"""A button that shows a solid colour and opens a colour picker.""" """A button that shows a solid colour and opens a colour picker."""
def __init__(self, color: str = "#89b4fa", parent=None): def __init__(self, color: str = "#8caaee", parent=None):
super().__init__(parent) super().__init__(parent)
self._color = color self._color = color
self.setFixedSize(32, 24) self.setFixedSize(32, 24)
@@ -26,7 +26,7 @@ class ColorButton(QPushButton):
def _refresh(self): def _refresh(self):
self.setStyleSheet( self.setStyleSheet(
f"background-color:{self._color}; border:1px solid #45475a; border-radius:4px;" f"background-color:{self._color}; border:1px solid #51576d; border-radius:4px;"
) )
def _pick(self): def _pick(self):
+11 -11
View File
@@ -36,12 +36,12 @@ def _cost_color(val_str: str) -> QColor:
try: try:
v = float(str(val_str).replace(",", "")) v = float(str(val_str).replace(",", ""))
except (ValueError, TypeError): except (ValueError, TypeError):
return QColor("#cdd6f4") # neutral (Catppuccin text) return QColor("#c6d0f5") # neutral (Catppuccin text)
if v <= 10: if v <= 10:
return QColor("#a6e3a1") # green — cheap return QColor("#a6d189") # green — cheap
if v <= 1_000: if v <= 1_000:
return QColor("#f9e2af") # yellow — moderate return QColor("#e5c890") # yellow — moderate
return QColor("#f38ba8") # red — expensive return QColor("#e78284") # red — expensive
# ── Background worker ───────────────────────────────────────────────────────── # ── Background worker ─────────────────────────────────────────────────────────
@@ -101,9 +101,9 @@ def _build_mysql_tree(tree: QTreeWidget, cols: list, rows: list):
good_types = {"const", "eq_ref", "ref", "system"} good_types = {"const", "eq_ref", "ref", "system"}
jt_lower = join_type.lower() jt_lower = join_type.lower()
if jt_lower in bad_types: if jt_lower in bad_types:
item.setForeground(1, QBrush(QColor("#f38ba8"))) item.setForeground(1, QBrush(QColor("#e78284")))
elif jt_lower in good_types: elif jt_lower in good_types:
item.setForeground(1, QBrush(QColor("#a6e3a1"))) item.setForeground(1, QBrush(QColor("#a6d189")))
# Colour rows estimate # Colour rows estimate
item.setForeground(3, QBrush(_cost_color(est_rows))) item.setForeground(3, QBrush(_cost_color(est_rows)))
@@ -203,9 +203,9 @@ def _build_sqlite_tree(tree: QTreeWidget, cols: list, rows: list):
# Colour SCAN (bad) vs SEARCH/INDEX (good) # Colour SCAN (bad) vs SEARCH/INDEX (good)
detail_str = str(detail).upper() detail_str = str(detail).upper()
if "SCAN" in detail_str and "INDEX" not in detail_str: if "SCAN" in detail_str and "INDEX" not in detail_str:
item.setForeground(1, QBrush(QColor("#f38ba8"))) item.setForeground(1, QBrush(QColor("#e78284")))
elif "INDEX" in detail_str or "SEARCH" in detail_str: elif "INDEX" in detail_str or "SEARCH" in detail_str:
item.setForeground(1, QBrush(QColor("#a6e3a1"))) item.setForeground(1, QBrush(QColor("#a6d189")))
items[rid] = item items[rid] = item
parent_item = items.get(parent) parent_item = items.get(parent)
@@ -334,8 +334,8 @@ class ExplainPanel(QWidget):
legend_row = QHBoxLayout() legend_row = QHBoxLayout()
legend_row.setContentsMargins(8, 2, 0, 4) legend_row.setContentsMargins(8, 2, 0, 4)
for colour, label in [ for colour, label in [
("#a6e3a1", "Efficient"), ("#f9e2af", "Moderate"), ("#a6d189", "Efficient"), ("#e5c890", "Moderate"),
("#f38ba8", "Expensive / SCAN"), ("#e78284", "Expensive / SCAN"),
]: ]:
dot = QLabel("") dot = QLabel("")
dot.setStyleSheet(f"color: {colour};") dot.setStyleSheet(f"color: {colour};")
@@ -414,7 +414,7 @@ class ExplainPanel(QWidget):
self._status_lbl.setText(f"Error: {msg[:80]}") self._status_lbl.setText(f"Error: {msg[:80]}")
self._tree.clear() self._tree.clear()
err_item = QTreeWidgetItem([f"{msg}"]) err_item = QTreeWidgetItem([f"{msg}"])
err_item.setForeground(0, QBrush(QColor("#f38ba8"))) err_item.setForeground(0, QBrush(QColor("#e78284")))
self._tree.setColumnCount(1) self._tree.setColumnCount(1)
self._tree.setHeaderLabels(["Error"]) self._tree.setHeaderLabels(["Error"])
self._tree.addTopLevelItem(err_item) self._tree.addTopLevelItem(err_item)
+9 -9
View File
@@ -30,14 +30,14 @@ from PyQt6.QtGui import (
from app.utils.logger import get_log_path from app.utils.logger import get_log_path
# ── Level colours (Catppuccin Mocha palette) ───────────────────────────────── # ── Level colours (Catppuccin Frappé palette) ─────────────────────────────────
_LEVEL_COLOURS: dict[str, str] = { _LEVEL_COLOURS: dict[str, str] = {
"DEBUG": "#6c7086", # surface2 / dimmed "DEBUG": "#737994", # overlay0 / dimmed
"INFO": "#cdd6f4", # text (default) "INFO": "#c6d0f5", # text (default)
"WARNING": "#f9e2af", # yellow "WARNING": "#e5c890", # yellow
"ERROR": "#f38ba8", # red "ERROR": "#e78284", # red
"CRITICAL": "#ff79c6", # pink / bright red "CRITICAL": "#f4b8e4", # pink / bright
} }
_LEVEL_ORDER = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] _LEVEL_ORDER = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
@@ -85,8 +85,8 @@ class _LogHighlighter(QSyntaxHighlighter):
# Highlight search matches in bright yellow # Highlight search matches in bright yellow
if self._search: if self._search:
search_fmt = QTextCharFormat() search_fmt = QTextCharFormat()
search_fmt.setBackground(QColor("#f9e2af")) search_fmt.setBackground(QColor("#e5c890"))
search_fmt.setForeground(QColor("#1e1e2e")) search_fmt.setForeground(QColor("#303446"))
idx = text.lower().find(self._search) idx = text.lower().find(self._search)
while idx != -1: while idx != -1:
self.setFormat(idx, len(self._search), search_fmt) self.setFormat(idx, len(self._search), search_fmt)
@@ -107,7 +107,7 @@ class _LevelBtn(QPushButton):
def _apply_style(self, checked: bool): def _apply_style(self, checked: bool):
if checked: if checked:
self.setStyleSheet( self.setStyleSheet(
f"QPushButton {{ background: {self._colour}; color: #1e1e2e; " f"QPushButton {{ background: {self._colour}; color: #303446; "
f"border: none; border-radius: 3px; font-weight: bold; }}" f"border: none; border-radius: 3px; font-weight: bold; }}"
) )
else: else:
+1 -1
View File
@@ -153,7 +153,7 @@ class QueryHistoryPanel(QWidget):
for c, val in enumerate(items): for c, val in enumerate(items):
item = QTableWidgetItem(val) item = QTableWidgetItem(val)
if c == 3 and status == "ERROR": if c == 3 and status == "ERROR":
item.setForeground(QColor("#f38ba8")) item.setForeground(QColor("#e78284"))
self._table.setItem(r, c, item) self._table.setItem(r, c, item)
def _filter(self, text: str): def _filter(self, text: str):
+4 -4
View File
@@ -96,7 +96,7 @@ class SchemaBrowser(QWidget):
# Dim colour — show the profile colour but muted # Dim colour — show the profile colour but muted
color = QColor(profile.color) color = QColor(profile.color)
color.setAlpha(140) color.setAlpha(140)
item.setForeground(0, QBrush(QColor("#6c7086"))) # greyed out item.setForeground(0, QBrush(QColor("#737994"))) # greyed out
item.setIcon(0, get_icon(profile.db_type, 16)) item.setIcon(0, get_icon(profile.db_type, 16))
item.setToolTip(0, self._connection_tooltip(profile)) item.setToolTip(0, self._connection_tooltip(profile))
@@ -350,9 +350,9 @@ class SchemaBrowser(QWidget):
child = QTreeWidgetItem([label]) child = QTreeWidgetItem([label])
child.setData(0, Qt.ItemDataRole.UserRole, (NT["column"], "", "", c.name)) child.setData(0, Qt.ItemDataRole.UserRole, (NT["column"], "", "", c.name))
if c.is_primary_key: if c.is_primary_key:
child.setForeground(0, QBrush(QColor("#f9e2af"))) child.setForeground(0, QBrush(QColor("#e5c890")))
elif c.is_foreign_key: elif c.is_foreign_key:
child.setForeground(0, QBrush(QColor("#89dceb"))) child.setForeground(0, QBrush(QColor("#99d1db")))
item.addChild(child) item.addChild(child)
def _load_indexes(self, item, pid, db, table): def _load_indexes(self, item, pid, db, table):
@@ -386,7 +386,7 @@ class SchemaBrowser(QWidget):
def _show_error(self, item, msg): def _show_error(self, item, msg):
err = QTreeWidgetItem([f"{msg}"]) err = QTreeWidgetItem([f"{msg}"])
err.setForeground(0, QBrush(QColor("#f38ba8"))) err.setForeground(0, QBrush(QColor("#e78284")))
item.addChild(err) item.addChild(err)
# ── Context menu ────────────────────────────────────────────────────────── # ── Context menu ──────────────────────────────────────────────────────────
+6 -6
View File
@@ -53,19 +53,19 @@ class _CompletionPopup(QListWidget):
self.setStyleSheet(""" self.setStyleSheet("""
QListWidget { QListWidget {
background: #1e1e2e; background: #292c3c;
color: #cdd6f4; color: #c6d0f5;
border: 1px solid #45475a; border: 1px solid #51576d;
border-radius: 4px; border-radius: 4px;
padding: 2px; padding: 2px;
outline: none; outline: none;
} }
QListWidget::item { padding: 2px 8px; } QListWidget::item { padding: 2px 8px; }
QListWidget::item:selected { QListWidget::item:selected {
background: #313244; background: #414559;
color: #cdd6f4; color: #c6d0f5;
} }
QListWidget::item:hover { background: #2a2a3c; } QListWidget::item:hover { background: #363a4f; }
""") """)
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded) self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
+4 -4
View File
@@ -81,7 +81,7 @@ class CodeEditor(QPlainTextEdit):
extra = [] extra = []
if not self.isReadOnly(): if not self.isReadOnly():
sel = QTextEdit.ExtraSelection() sel = QTextEdit.ExtraSelection()
sel.format.setBackground(QColor("#2a2a3c")) sel.format.setBackground(QColor("#3d4155"))
sel.format.setProperty(QTextFormat.Property.FullWidthSelection, True) sel.format.setProperty(QTextFormat.Property.FullWidthSelection, True)
sel.cursor = self.textCursor() sel.cursor = self.textCursor()
sel.cursor.clearSelection() sel.cursor.clearSelection()
@@ -90,7 +90,7 @@ class CodeEditor(QPlainTextEdit):
def line_number_area_paint_event(self, event): def line_number_area_paint_event(self, event):
painter = QPainter(self._line_area) painter = QPainter(self._line_area)
painter.fillRect(event.rect(), QColor("#1a1a2e")) painter.fillRect(event.rect(), QColor("#2a2d3e"))
block = self.firstVisibleBlock() block = self.firstVisibleBlock()
number = block.blockNumber() number = block.blockNumber()
@@ -100,7 +100,7 @@ class CodeEditor(QPlainTextEdit):
while block.isValid() and top <= event.rect().bottom(): while block.isValid() and top <= event.rect().bottom():
if block.isVisible() and bottom >= event.rect().top(): if block.isVisible() and bottom >= event.rect().top():
painter.setPen(QColor("#45475a")) painter.setPen(QColor("#51576d"))
painter.drawText( painter.drawText(
0, top, self._line_area.width() - 6, 0, top, self._line_area.width() - 6,
self.fontMetrics().height(), self.fontMetrics().height(),
@@ -339,7 +339,7 @@ class FindBar(QWidget):
self._do_find(backward=True) self._do_find(backward=True)
def _set_no_match(self, no_match: bool): def _set_no_match(self, no_match: bool):
color = "#f38ba8" if no_match else "" color = "#e78284" if no_match else ""
self._find_input.setStyleSheet( self._find_input.setStyleSheet(
f"background: {color};" if no_match else "" f"background: {color};" if no_match else ""
) )
+11 -11
View File
@@ -17,15 +17,15 @@ def _fmt(color: str, bold: bool = False, italic: bool = False) -> QTextCharForma
return f return f
# ── Token categories (Catppuccin Mocha palette) ─────────────────────────────── # ── Token categories (Catppuccin Frappé palette) ─────────────────────────────
_KEYWORD_FMT = _fmt("#89b4fa", bold=True) # blue — DDL/DML/control _KEYWORD_FMT = _fmt("#8caaee", bold=True) # blue — DDL/DML/control
_TYPE_FMT = _fmt("#fab387") # peach — data types _TYPE_FMT = _fmt("#ef9f76") # peach — data types
_FUNCTION_FMT = _fmt("#a6e3a1") # green — functions _FUNCTION_FMT = _fmt("#a6d189") # green — functions
_STRING_FMT = _fmt("#a6e3a1") # green — string literals _STRING_FMT = _fmt("#a6d189") # green — string literals
_NUMBER_FMT = _fmt("#fab387") # orange — numeric literals _NUMBER_FMT = _fmt("#ef9f76") # orange — numeric literals
_COMMENT_FMT = _fmt("#6c7086", italic=True) # grey — comments _COMMENT_FMT = _fmt("#737994", italic=True) # grey — comments
_OPERATOR_FMT = _fmt("#cba6f7") # mauve — operators/special _OPERATOR_FMT = _fmt("#ca9ee6") # mauve — operators/special
_STAR_FMT = _fmt("#cba6f7", bold=True) # mauve — * wildcard _STAR_FMT = _fmt("#ca9ee6", bold=True) # mauve — * wildcard
# ── Keyword lists ───────────────────────────────────────────────────────────── # ── Keyword lists ─────────────────────────────────────────────────────────────
_KEYWORDS = [ _KEYWORDS = [
@@ -101,9 +101,9 @@ class SQLHighlighter(QSyntaxHighlighter):
# Single-quoted strings # Single-quoted strings
(QRegularExpression(r"'[^'\\]*(?:\\.[^'\\]*)*'"), _STRING_FMT), (QRegularExpression(r"'[^'\\]*(?:\\.[^'\\]*)*'"), _STRING_FMT),
# Double-quoted identifiers # Double-quoted identifiers
(QRegularExpression(r'"[^"]*"'), _fmt("#89dceb")), (QRegularExpression(r'"[^"]*"'), _fmt("#99d1db")),
# Backtick identifiers (MySQL) # Backtick identifiers (MySQL)
(QRegularExpression(r"`[^`]*`"), _fmt("#89dceb")), (QRegularExpression(r"`[^`]*`"), _fmt("#99d1db")),
# * wildcard # * wildcard
(QRegularExpression(r"\bSELECT\s+\*|\*(?=\s*FROM)", (QRegularExpression(r"\bSELECT\s+\*|\*(?=\s*FROM)",
QRegularExpression.PatternOption.CaseInsensitiveOption), QRegularExpression.PatternOption.CaseInsensitiveOption),
+2 -2
View File
@@ -171,9 +171,9 @@ class TableStructureView(QWidget):
item = QTableWidgetItem(str(val)) item = QTableWidgetItem(str(val))
item.setTextAlignment(Qt.AlignmentFlag.AlignCenter) item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
if col.is_primary_key and c == 0: if col.is_primary_key and c == 0:
item.setForeground(QColor("#f9e2af")) item.setForeground(QColor("#e5c890"))
elif col.is_foreign_key and c == 0: elif col.is_foreign_key and c == 0:
item.setForeground(QColor("#89dceb")) item.setForeground(QColor("#99d1db"))
t.setItem(r, c, item) t.setItem(r, c, item)
def _load_indexes(self): def _load_indexes(self):
+6 -6
View File
@@ -148,17 +148,17 @@ class EditableTableModel(QAbstractTableModel):
if role == Qt.ItemDataRole.ForegroundRole: if role == Qt.ItemDataRole.ForegroundRole:
if self._is_deleted_row(r): if self._is_deleted_row(r):
return QBrush(QColor("#f38ba8")) # red — pending delete return QBrush(QColor("#e78284")) # red — pending delete
if (r, c) in self._dirty: if (r, c) in self._dirty:
return QBrush(QColor("#fab387")) # orange — edited return QBrush(QColor("#ef9f76")) # orange — edited
if val is None: if val is None:
return QBrush(QColor("#6c7086")) # grey — NULL return QBrush(QColor("#737994")) # grey — NULL
if role == Qt.ItemDataRole.BackgroundRole: if role == Qt.ItemDataRole.BackgroundRole:
if self._is_deleted_row(r): if self._is_deleted_row(r):
return QBrush(QColor("#2a1a1e")) return QBrush(QColor("#3a2530"))
if (r, c) in self._dirty: if (r, c) in self._dirty:
return QBrush(QColor("#2a1f1a")) return QBrush(QColor("#3a2f25"))
return None return None
@@ -351,7 +351,7 @@ class TableViewer(QWidget):
# Separator # Separator
sep = QLabel("|") sep = QLabel("|")
sep.setStyleSheet("color:#45475a; padding:0 4px;") sep.setStyleSheet("color:#51576d; padding:0 4px;")
# CRUD buttons # CRUD buttons
self._add_btn = QPushButton(" Add") self._add_btn = QPushButton(" Add")
+1 -1
View File
@@ -64,7 +64,7 @@ ICONS = {
def make_icon(glyph: str, size: int = 20, def make_icon(glyph: str, size: int = 20,
fg: str = "#cdd6f4", bg: str = "transparent") -> QIcon: fg: str = "#c6d0f5", bg: str = "transparent") -> QIcon:
"""Create a QIcon from a Unicode glyph.""" """Create a QIcon from a Unicode glyph."""
px = QPixmap(QSize(size, size)) px = QPixmap(QSize(size, size))
px.fill(Qt.GlobalColor.transparent) px.fill(Qt.GlobalColor.transparent)
+161 -161
View File
@@ -1,15 +1,15 @@
/* ═══════════════════════════════════════════════════════════════════════════ /* ═══════════════════════════════════════════════════════════════════════════
DBClient — Dark Theme (Catppuccin Mocha palette) DBClient — Dark Theme (Catppuccin Frappé palette)
═══════════════════════════════════════════════════════════════════════════ */ ═══════════════════════════════════════════════════════════════════════════ */
/* ── Variables via flat tokens ───────────────────────────────────────────── /* ── Variables via flat tokens ─────────────────────────────────────────────
base #1e1e2e crust #11111b base #303446 crust #232634
surface0 #313244 surface1 #45475a surface2 #585b70 surface0 #414559 surface1 #51576d surface2 #626880
overlay #6c7086 subtext #a6adc8 text #cdd6f4 overlay #737994 subtext #a5adce text #c6d0f5
blue #89b4fa lavender #b4befe sapphire #74c7ec blue #8caaee lavender #babbf1 sapphire #85c1dc
green #a6e3a1 teal #94e2d5 sky #89dceb green #a6d189 teal #81c8be sky #99d1db
mauve #cba6f7 pink #f5c2e7 red #f38ba8 mauve #ca9ee6 pink #f4b8e4 red #e78284
peach #fab387 yellow #f9e2af peach #ef9f76 yellow #e5c890
─────────────────────────────────────────────────────────────────────── */ ─────────────────────────────────────────────────────────────────────── */
/* ── Global reset ───────────────────────────────────────────────────────── */ /* ── Global reset ───────────────────────────────────────────────────────── */
@@ -18,22 +18,22 @@
} }
QMainWindow, QDialog { QMainWindow, QDialog {
background-color: #1e1e2e; background-color: #303446;
color: #cdd6f4; color: #c6d0f5;
} }
QWidget { QWidget {
background-color: #1e1e2e; background-color: #303446;
color: #cdd6f4; color: #c6d0f5;
font-family: "Segoe UI", "Inter", sans-serif; font-family: "Segoe UI", "Inter", sans-serif;
font-size: 10pt; font-size: 10pt;
} }
/* ── Menu bar ───────────────────────────────────────────────────────────── */ /* ── Menu bar ───────────────────────────────────────────────────────────── */
QMenuBar { QMenuBar {
background-color: #11111b; background-color: #232634;
color: #cdd6f4; color: #c6d0f5;
border-bottom: 1px solid #313244; border-bottom: 1px solid #414559;
padding: 2px 0; padding: 2px 0;
} }
@@ -43,12 +43,12 @@ QMenuBar::item {
} }
QMenuBar::item:selected { QMenuBar::item:selected {
background-color: #313244; background-color: #414559;
} }
QMenu { QMenu {
background-color: #181825; background-color: #292c3c;
border: 1px solid #45475a; border: 1px solid #51576d;
border-radius: 6px; border-radius: 6px;
padding: 4px; padding: 4px;
} }
@@ -56,59 +56,59 @@ QMenu {
QMenu::item { QMenu::item {
padding: 6px 24px 6px 12px; padding: 6px 24px 6px 12px;
border-radius: 4px; border-radius: 4px;
color: #cdd6f4; color: #c6d0f5;
} }
QMenu::item:selected { QMenu::item:selected {
background-color: #313244; background-color: #414559;
color: #cdd6f4; color: #c6d0f5;
} }
QMenu::separator { QMenu::separator {
height: 1px; height: 1px;
background: #45475a; background: #51576d;
margin: 4px 8px; margin: 4px 8px;
} }
/* ── Status bar ─────────────────────────────────────────────────────────── */ /* ── Status bar ─────────────────────────────────────────────────────────── */
QStatusBar { QStatusBar {
background-color: #11111b; background-color: #232634;
border-top: 1px solid #313244; border-top: 1px solid #414559;
color: #a6adc8; color: #a5adce;
font-size: 9pt; font-size: 9pt;
padding: 2px 8px; padding: 2px 8px;
} }
/* ── Scrollbars ─────────────────────────────────────────────────────────── */ /* ── Scrollbars ─────────────────────────────────────────────────────────── */
QScrollBar:vertical { QScrollBar:vertical {
background: #1e1e2e; background: #303446;
width: 10px; width: 10px;
margin: 0; margin: 0;
} }
QScrollBar::handle:vertical { QScrollBar::handle:vertical {
background: #45475a; background: #51576d;
border-radius: 5px; border-radius: 5px;
min-height: 24px; min-height: 24px;
} }
QScrollBar::handle:vertical:hover { QScrollBar::handle:vertical:hover {
background: #585b70; background: #626880;
} }
QScrollBar:horizontal { QScrollBar:horizontal {
background: #1e1e2e; background: #303446;
height: 10px; height: 10px;
} }
QScrollBar::handle:horizontal { QScrollBar::handle:horizontal {
background: #45475a; background: #51576d;
border-radius: 5px; border-radius: 5px;
min-width: 24px; min-width: 24px;
} }
QScrollBar::handle:horizontal:hover { QScrollBar::handle:horizontal:hover {
background: #585b70; background: #626880;
} }
QScrollBar::add-line, QScrollBar::sub-line { height: 0; width: 0; } QScrollBar::add-line, QScrollBar::sub-line { height: 0; width: 0; }
@@ -116,47 +116,47 @@ QScrollBar::add-page, QScrollBar::sub-page { background: transparent; }
/* ── Splitter ────────────────────────────────────────────────────────────── */ /* ── Splitter ────────────────────────────────────────────────────────────── */
QSplitter::handle { QSplitter::handle {
background-color: #313244; background-color: #414559;
} }
QSplitter::handle:horizontal { width: 2px; } QSplitter::handle:horizontal { width: 2px; }
QSplitter::handle:vertical { height: 2px; } QSplitter::handle:vertical { height: 2px; }
QSplitter::handle:hover { QSplitter::handle:hover {
background-color: #89b4fa; background-color: #8caaee;
} }
/* ── Sidebar ─────────────────────────────────────────────────────────────── */ /* ── Sidebar ─────────────────────────────────────────────────────────────── */
#sidebarHeader { #sidebarHeader {
background-color: #181825; background-color: #292c3c;
border-bottom: 1px solid #313244; border-bottom: 1px solid #414559;
} }
#sidebarTitle { #sidebarTitle {
color: #89b4fa; color: #8caaee;
font-size: 11pt; font-size: 11pt;
font-weight: 600; font-weight: 600;
} }
#newConnBtn { #newConnBtn {
background-color: #313244; background-color: #414559;
color: #89b4fa; color: #8caaee;
border: 1px solid #45475a; border: 1px solid #51576d;
border-radius: 6px; border-radius: 6px;
font-size: 14pt; font-size: 14pt;
padding: 0; padding: 0;
} }
#newConnBtn:hover { #newConnBtn:hover {
background-color: #45475a; background-color: #51576d;
color: #b4befe; color: #babbf1;
} }
/* ── Tree widget ─────────────────────────────────────────────────────────── */ /* ── Tree widget ─────────────────────────────────────────────────────────── */
QTreeWidget { QTreeWidget {
background-color: #181825; background-color: #292c3c;
border: none; border: none;
color: #cdd6f4; color: #c6d0f5;
font-size: 10pt; font-size: 10pt;
show-decoration-selected: 1; show-decoration-selected: 1;
} }
@@ -167,12 +167,12 @@ QTreeWidget::item {
} }
QTreeWidget::item:hover { QTreeWidget::item:hover {
background-color: #2a2a3c; background-color: #363a4f;
} }
QTreeWidget::item:selected { QTreeWidget::item:selected {
background-color: #313244; background-color: #414559;
color: #cdd6f4; color: #c6d0f5;
} }
QTreeWidget::branch { QTreeWidget::branch {
@@ -182,32 +182,32 @@ QTreeWidget::branch {
/* ── Tab widget ──────────────────────────────────────────────────────────── */ /* ── Tab widget ──────────────────────────────────────────────────────────── */
QTabWidget::pane { QTabWidget::pane {
border: none; border: none;
border-top: 1px solid #313244; border-top: 1px solid #414559;
background-color: #1e1e2e; background-color: #303446;
} }
QTabBar { QTabBar {
background-color: #181825; background-color: #292c3c;
} }
QTabBar::tab { QTabBar::tab {
background-color: #181825; background-color: #292c3c;
color: #a6adc8; color: #a5adce;
padding: 7px 16px; padding: 7px 16px;
border: none; border: none;
border-right: 1px solid #313244; border-right: 1px solid #414559;
font-size: 10pt; font-size: 10pt;
} }
QTabBar::tab:selected { QTabBar::tab:selected {
background-color: #1e1e2e; background-color: #303446;
color: #cdd6f4; color: #c6d0f5;
border-bottom: 2px solid #89b4fa; border-bottom: 2px solid #8caaee;
} }
QTabBar::tab:hover:!selected { QTabBar::tab:hover:!selected {
background-color: #252536; background-color: #353849;
color: #cdd6f4; color: #c6d0f5;
} }
QTabBar::close-button { QTabBar::close-button {
@@ -217,13 +217,13 @@ QTabBar::close-button {
/* ── Table view ──────────────────────────────────────────────────────────── */ /* ── Table view ──────────────────────────────────────────────────────────── */
QTableView, QTableWidget { QTableView, QTableWidget {
background-color: #1e1e2e; background-color: #303446;
alternate-background-color: #252538; alternate-background-color: #363a4f;
gridline-color: #313244; gridline-color: #414559;
color: #cdd6f4; color: #c6d0f5;
border: none; border: none;
selection-background-color: #313244; selection-background-color: #414559;
selection-color: #cdd6f4; selection-color: #c6d0f5;
font-size: 10pt; font-size: 10pt;
} }
@@ -232,29 +232,29 @@ QTableView::item, QTableWidget::item {
} }
QHeaderView { QHeaderView {
background-color: #181825; background-color: #292c3c;
} }
QHeaderView::section { QHeaderView::section {
background-color: #181825; background-color: #292c3c;
color: #89b4fa; color: #8caaee;
border: none; border: none;
border-right: 1px solid #313244; border-right: 1px solid #414559;
border-bottom: 1px solid #313244; border-bottom: 1px solid #414559;
padding: 4px 8px; padding: 4px 8px;
font-weight: 600; font-weight: 600;
} }
QHeaderView::section:hover { QHeaderView::section:hover {
background-color: #252536; background-color: #353849;
} }
/* ── Plain text edit (SQL editor body) ───────────────────────────────────── */ /* ── Plain text edit (SQL editor body) ───────────────────────────────────── */
QPlainTextEdit { QPlainTextEdit {
background-color: #1e1e2e; background-color: #303446;
color: #cdd6f4; color: #c6d0f5;
border: none; border: none;
selection-background-color: #45475a; selection-background-color: #51576d;
font-family: "Consolas", "JetBrains Mono", "Courier New", monospace; font-family: "Consolas", "JetBrains Mono", "Courier New", monospace;
font-size: 13pt; font-size: 13pt;
line-height: 1.5; line-height: 1.5;
@@ -262,126 +262,126 @@ QPlainTextEdit {
/* ── Line number gutter ──────────────────────────────────────────────────── */ /* ── Line number gutter ──────────────────────────────────────────────────── */
LineNumberArea { LineNumberArea {
background-color: #1a1a2e; background-color: #2a2d3e;
} }
/* ── Buttons ─────────────────────────────────────────────────────────────── */ /* ── Buttons ─────────────────────────────────────────────────────────────── */
QPushButton { QPushButton {
background-color: #313244; background-color: #414559;
color: #cdd6f4; color: #c6d0f5;
border: 1px solid #45475a; border: 1px solid #51576d;
border-radius: 6px; border-radius: 6px;
padding: 5px 14px; padding: 5px 14px;
font-size: 10pt; font-size: 10pt;
} }
QPushButton:hover { QPushButton:hover {
background-color: #45475a; background-color: #51576d;
border-color: #585b70; border-color: #626880;
} }
QPushButton:pressed { QPushButton:pressed {
background-color: #252536; background-color: #363849;
} }
QPushButton:disabled { QPushButton:disabled {
color: #585b70; color: #626880;
background-color: #252536; background-color: #363849;
border-color: #313244; border-color: #414559;
} }
#runBtn { #runBtn {
background-color: #a6e3a1; background-color: #a6d189;
color: #1e1e2e; color: #303446;
font-weight: 700; font-weight: 700;
border: none; border: none;
} }
#runBtn:hover { #runBtn:hover {
background-color: #94e2d5; background-color: #81c8be;
} }
#stopBtn { #stopBtn {
background-color: #f38ba8; background-color: #e78284;
color: #1e1e2e; color: #303446;
font-weight: 700; font-weight: 700;
border: none; border: none;
} }
#stopBtn:hover { #stopBtn:hover {
background-color: #eba0ac; background-color: #ea999c;
} }
#commitBtn { #commitBtn {
background-color: #a6e3a1; background-color: #a6d189;
color: #1e1e2e; color: #303446;
font-weight: 700; font-weight: 700;
border: none; border: none;
} }
#rollbackBtn { #rollbackBtn {
background-color: #fab387; background-color: #ef9f76;
color: #1e1e2e; color: #303446;
font-weight: 700; font-weight: 700;
border: none; border: none;
} }
#crudAddBtn { #crudAddBtn {
background-color: #313244; background-color: #414559;
color: #a6e3a1; color: #a6d189;
border: 1px solid #a6e3a1; border: 1px solid #a6d189;
font-weight: 600; font-weight: 600;
} }
#crudAddBtn:hover { #crudAddBtn:hover {
background-color: #a6e3a1; background-color: #a6d189;
color: #1e1e2e; color: #303446;
} }
#crudDeleteBtn { #crudDeleteBtn {
background-color: #313244; background-color: #414559;
color: #f38ba8; color: #e78284;
border: 1px solid #f38ba8; border: 1px solid #e78284;
font-weight: 600; font-weight: 600;
} }
#crudDeleteBtn:hover { #crudDeleteBtn:hover {
background-color: #f38ba8; background-color: #e78284;
color: #1e1e2e; color: #303446;
} }
/* ── Line edit ───────────────────────────────────────────────────────────── */ /* ── Line edit ───────────────────────────────────────────────────────────── */
QLineEdit { QLineEdit {
background-color: #313244; background-color: #414559;
color: #cdd6f4; color: #c6d0f5;
border: 1px solid #45475a; border: 1px solid #51576d;
border-radius: 6px; border-radius: 6px;
padding: 5px 10px; padding: 5px 10px;
font-size: 10pt; font-size: 10pt;
selection-background-color: #89b4fa; selection-background-color: #8caaee;
selection-color: #1e1e2e; selection-color: #303446;
} }
QLineEdit:focus { QLineEdit:focus {
border-color: #89b4fa; border-color: #8caaee;
} }
QLineEdit::placeholder { QLineEdit::placeholder {
color: #585b70; color: #626880;
} }
/* ── Combo box ───────────────────────────────────────────────────────────── */ /* ── Combo box ───────────────────────────────────────────────────────────── */
QComboBox { QComboBox {
background-color: #313244; background-color: #414559;
color: #cdd6f4; color: #c6d0f5;
border: 1px solid #45475a; border: 1px solid #51576d;
border-radius: 6px; border-radius: 6px;
padding: 5px 10px; padding: 5px 10px;
font-size: 10pt; font-size: 10pt;
} }
QComboBox:focus { QComboBox:focus {
border-color: #89b4fa; border-color: #8caaee;
} }
QComboBox::drop-down { QComboBox::drop-down {
@@ -390,25 +390,25 @@ QComboBox::drop-down {
} }
QComboBox QAbstractItemView { QComboBox QAbstractItemView {
background-color: #181825; background-color: #292c3c;
color: #cdd6f4; color: #c6d0f5;
border: 1px solid #45475a; border: 1px solid #51576d;
selection-background-color: #313244; selection-background-color: #414559;
} }
/* ── Spin box ────────────────────────────────────────────────────────────── */ /* ── Spin box ────────────────────────────────────────────────────────────── */
QSpinBox { QSpinBox {
background-color: #313244; background-color: #414559;
color: #cdd6f4; color: #c6d0f5;
border: 1px solid #45475a; border: 1px solid #51576d;
border-radius: 6px; border-radius: 6px;
padding: 4px 8px; padding: 4px 8px;
} }
QSpinBox:focus { border-color: #89b4fa; } QSpinBox:focus { border-color: #8caaee; }
QSpinBox::up-button, QSpinBox::down-button { QSpinBox::up-button, QSpinBox::down-button {
background-color: #45475a; background-color: #51576d;
border: none; border: none;
border-radius: 3px; border-radius: 3px;
width: 16px; width: 16px;
@@ -416,26 +416,26 @@ QSpinBox::up-button, QSpinBox::down-button {
/* ── Check box ───────────────────────────────────────────────────────────── */ /* ── Check box ───────────────────────────────────────────────────────────── */
QCheckBox { QCheckBox {
color: #cdd6f4; color: #c6d0f5;
spacing: 8px; spacing: 8px;
} }
QCheckBox::indicator { QCheckBox::indicator {
width: 16px; width: 16px;
height: 16px; height: 16px;
border: 2px solid #45475a; border: 2px solid #51576d;
border-radius: 4px; border-radius: 4px;
background: #313244; background: #414559;
} }
QCheckBox::indicator:checked { QCheckBox::indicator:checked {
background-color: #89b4fa; background-color: #8caaee;
border-color: #89b4fa; border-color: #8caaee;
} }
/* ── Dialog ──────────────────────────────────────────────────────────────── */ /* ── Dialog ──────────────────────────────────────────────────────────────── */
QDialog { QDialog {
background-color: #1e1e2e; background-color: #303446;
} }
QDialogButtonBox QPushButton { QDialogButtonBox QPushButton {
@@ -444,22 +444,22 @@ QDialogButtonBox QPushButton {
/* ── Form layout labels ──────────────────────────────────────────────────── */ /* ── Form layout labels ──────────────────────────────────────────────────── */
QFormLayout QLabel { QFormLayout QLabel {
color: #a6adc8; color: #a5adce;
} }
/* ── Tab widget in dialogs ───────────────────────────────────────────────── */ /* ── Tab widget in dialogs ───────────────────────────────────────────────── */
QTabWidget#dialogTabs::pane { QTabWidget#dialogTabs::pane {
border: 1px solid #313244; border: 1px solid #414559;
border-radius: 6px; border-radius: 6px;
margin-top: -1px; margin-top: -1px;
} }
/* ── Group box ───────────────────────────────────────────────────────────── */ /* ── Group box ───────────────────────────────────────────────────────────── */
QGroupBox { QGroupBox {
border: 1px solid #45475a; border: 1px solid #51576d;
border-radius: 6px; border-radius: 6px;
margin-top: 1em; margin-top: 1em;
color: #a6adc8; color: #a5adce;
font-weight: 600; font-weight: 600;
} }
@@ -471,72 +471,72 @@ QGroupBox::title {
/* ── Progress bar ────────────────────────────────────────────────────────── */ /* ── Progress bar ────────────────────────────────────────────────────────── */
QProgressBar { QProgressBar {
background-color: #313244; background-color: #414559;
border: 1px solid #45475a; border: 1px solid #51576d;
border-radius: 6px; border-radius: 6px;
height: 10px; height: 10px;
text-align: center; text-align: center;
} }
QProgressBar::chunk { QProgressBar::chunk {
background-color: #89b4fa; background-color: #8caaee;
border-radius: 5px; border-radius: 5px;
} }
/* ── Dock widget ─────────────────────────────────────────────────────────── */ /* ── Dock widget ─────────────────────────────────────────────────────────── */
QDockWidget { QDockWidget {
color: #cdd6f4; color: #c6d0f5;
titlebar-close-icon: none; titlebar-close-icon: none;
font-weight: 600; font-weight: 600;
} }
QDockWidget::title { QDockWidget::title {
background-color: #181825; background-color: #292c3c;
padding: 6px; padding: 6px;
border-bottom: 1px solid #313244; border-bottom: 1px solid #414559;
} }
/* ── Tool button ─────────────────────────────────────────────────────────── */ /* ── Tool button ─────────────────────────────────────────────────────────── */
QToolButton { QToolButton {
background-color: #313244; background-color: #414559;
color: #cdd6f4; color: #c6d0f5;
border: 1px solid #45475a; border: 1px solid #51576d;
border-radius: 5px; border-radius: 5px;
padding: 4px 8px; padding: 4px 8px;
font-size: 13pt; font-size: 13pt;
} }
QToolButton:hover { QToolButton:hover {
background-color: #45475a; background-color: #51576d;
} }
/* ── Message box ─────────────────────────────────────────────────────────── */ /* ── Message box ─────────────────────────────────────────────────────────── */
QMessageBox { QMessageBox {
background-color: #1e1e2e; background-color: #303446;
} }
QMessageBox QLabel { QMessageBox QLabel {
color: #cdd6f4; color: #c6d0f5;
font-size: 10pt; font-size: 10pt;
} }
/* ── Empty workspace label ───────────────────────────────────────────────── */ /* ── Empty workspace label ───────────────────────────────────────────────── */
#emptyLabel { #emptyLabel {
color: #585b70; color: #626880;
font-size: 14pt; font-size: 14pt;
line-height: 2; line-height: 2;
} }
/* ── Status label in results toolbar ────────────────────────────────────── */ /* ── Status label in results toolbar ────────────────────────────────────── */
#statusLabel { #statusLabel {
color: #a6adc8; color: #a5adce;
font-size: 9pt; font-size: 9pt;
padding-left: 4px; padding-left: 4px;
} }
/* ── DB label in SQL editor toolbar ─────────────────────────────────────── */ /* ── DB label in SQL editor toolbar ─────────────────────────────────────── */
#dbLabel { #dbLabel {
color: #6c7086; color: #737994;
font-size: 9pt; font-size: 9pt;
padding-right: 4px; padding-right: 4px;
} }
@@ -548,26 +548,26 @@ QMessageBox QLabel {
/* ── Horizontal separator line in dialog ────────────────────────────────── */ /* ── Horizontal separator line in dialog ────────────────────────────────── */
QFrame[frameShape="4"] { /* HLine */ QFrame[frameShape="4"] { /* HLine */
color: #313244; color: #414559;
margin: 4px 0; margin: 4px 0;
} }
/* ── Structure view title ────────────────────────────────────────────────── */ /* ── Structure view title ────────────────────────────────────────────────── */
#structureTitle { #structureTitle {
color: #b4befe; color: #babbf1;
} }
/* ── Pagination bar ──────────────────────────────────────────────────────── */ /* ── Pagination bar ──────────────────────────────────────────────────────── */
#paginationBar { #paginationBar {
background-color: #181825; background-color: #292c3c;
border-top: 1px solid #45475a; border-top: 1px solid #51576d;
min-height: 38px; min-height: 38px;
} }
#pgBtn { #pgBtn {
background-color: #252536; background-color: #363849;
color: #cdd6f4; color: #c6d0f5;
border: 1px solid #45475a; border: 1px solid #51576d;
border-radius: 5px; border-radius: 5px;
padding: 4px 10px; padding: 4px 10px;
font-size: 9pt; font-size: 9pt;
@@ -575,25 +575,25 @@ QFrame[frameShape="4"] { /* HLine */
} }
#pgBtn:hover { #pgBtn:hover {
background-color: #313244; background-color: #414559;
border-color: #585b70; border-color: #626880;
} }
#pgBtn:disabled { #pgBtn:disabled {
color: #45475a; color: #51576d;
background-color: #1e1e2e; background-color: #303446;
border-color: #313244; border-color: #414559;
} }
#pageLbl { #pageLbl {
color: #89b4fa; color: #8caaee;
font-size: 9pt; font-size: 9pt;
font-weight: 600; font-weight: 600;
padding: 0 6px; padding: 0 6px;
} }
#rowCountLbl { #rowCountLbl {
color: #a6adc8; color: #a5adce;
font-size: 9pt; font-size: 9pt;
padding-left: 8px; padding-left: 8px;
} }