fix: address settings width and overlay review

This commit is contained in:
Yasin Özmen
2026-08-27 15:57:52 +03:00
parent bcd6b81d23
commit 9b03da4175
3 changed files with 74 additions and 23 deletions
-7
View File
@@ -272,13 +272,6 @@ class Overlay(QWidget):
if self.below is not None and self.below.showing != self._stacked:
self._reposition()
elif self.state in LIVE:
# Follow the screen the mouse is currently on. Checked every ten
# ticks (~333 ms) rather than every frame: screenAt() is cheap but
# the user's hand moves slowly, so there is no value in sampling it
# at 30 Hz.
self._screen_check_ticks = getattr(self, "_screen_check_ticks", 0) + 1
if self._screen_check_ticks >= 10:
self._screen_check_ticks = 0
current_screen = QApplication.screenAt(QCursor.pos())
if current_screen is not None and current_screen != self.screen():
self._reposition()
+19 -12
View File
@@ -12,7 +12,7 @@ from PyQt6.QtWidgets import (
QAbstractItemView, QAbstractSpinBox, QCheckBox, QComboBox, QDialog,
QDialogButtonBox, QFileDialog, QFormLayout, QGroupBox, QHBoxLayout, QLabel,
QLineEdit, QListWidget, QListWidgetItem, QMenu, QMessageBox, QPlainTextEdit,
QPushButton, QScrollArea, QSpinBox, QTabWidget, QVBoxLayout, QWidget, QSizePolicy,
QPushButton, QScrollArea, QSpinBox, QTabWidget, QVBoxLayout, QWidget,
)
from . import __version__
@@ -229,6 +229,8 @@ class LocalModelBox(QGroupBox):
self._wanted = "" # the model to select once a list arrives
form = QFormLayout(self)
form.setFieldGrowthPolicy(
QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
self.program_label = WrappedLabel()
self.install_button = QPushButton(t("Download"))
@@ -239,7 +241,6 @@ class LocalModelBox(QGroupBox):
if self._repos is not None:
self.repo = QComboBox()
self.repo.setEditable(True)
self.repo.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.repo.setToolTip(t("A Hugging Face repository of GGUF files. The "
"list is fetched; any other one can be typed in."))
self.repo.currentTextChanged.connect(self._repo_changed)
@@ -679,6 +680,8 @@ class SettingsWindow(QDialog):
def _general_tab(self):
page = QWidget()
form = QFormLayout(page)
form.setFieldGrowthPolicy(
QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
self.ui_language = QComboBox()
for label, code in UI_LANGUAGES:
@@ -704,7 +707,6 @@ class SettingsWindow(QDialog):
# them: a stored one this desktop does not offer is kept as it is
# rather than quietly replaced by the first item on the list.
self.paste_shortcut.setEditable(True)
self.paste_shortcut.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.paste_shortcut.addItems(paste.desktop().shortcuts)
self.paste_shortcut.setToolTip(t(
"macOS asks for Accessibility permission the first time this is sent."
@@ -792,6 +794,8 @@ class SettingsWindow(QDialog):
stt = QGroupBox(t("Speech to text"))
stt_form = QFormLayout(stt)
stt_form.setFieldGrowthPolicy(
QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
self.transcribe_provider = QComboBox()
for label, value in TRANSCRIBE_PROVIDERS:
self.transcribe_provider.addItem(t(label), value)
@@ -803,7 +807,6 @@ class SettingsWindow(QDialog):
self.stt_form = stt_form
self.transcribe_model = QComboBox()
self.transcribe_model.setEditable(True)
self.transcribe_model.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.refresh_transcribe_models = QPushButton(t("Fetch model list"))
self.refresh_transcribe_models.clicked.connect(self._load_transcribe_models)
self.transcribe_model_row = self._row(self.transcribe_model,
@@ -854,6 +857,8 @@ class SettingsWindow(QDialog):
orr = QGroupBox(t("Transcript cleanup"))
orr_form = self.cleanup_form = QFormLayout(orr)
orr_form.setFieldGrowthPolicy(
QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
self.cleanup_enabled = QCheckBox(t("Clean the transcript with a model"))
orr_form.addRow("", self.cleanup_enabled)
@@ -872,7 +877,6 @@ class SettingsWindow(QDialog):
self.cleanup_model = QComboBox()
self.cleanup_model.setEditable(True)
self.cleanup_model.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.cleanup_model.addItems(CLEANUP_MODELS)
self.refresh_models = QPushButton(t("Fetch model list"))
self.refresh_models.clicked.connect(self._load_models)
@@ -884,14 +888,12 @@ class SettingsWindow(QDialog):
# field, and only the row of whoever is chosen is on screen.
self.cleanup_claude_model = QComboBox()
self.cleanup_claude_model.setEditable(True)
self.cleanup_claude_model.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.cleanup_claude_model.addItems(CLEANUP_CLAUDE_MODELS)
self.cleanup_claude_model.setToolTip(_typed_model_note("Claude Code"))
orr_form.addRow(t("Model"), self.cleanup_claude_model)
self.cleanup_codex_model = QComboBox()
self.cleanup_codex_model.setEditable(True)
self.cleanup_codex_model.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.cleanup_codex_model.addItems([t("Codex's own default")] + CODEX_MODELS)
self.cleanup_codex_model.setToolTip(_typed_model_note("Codex"))
orr_form.addRow(t("Model"), self.cleanup_codex_model)
@@ -1046,9 +1048,10 @@ class SettingsWindow(QDialog):
# be worse than none.
self.claude_box = QGroupBox(t("Claude Code"))
claude_form = QFormLayout(self.claude_box)
claude_form.setFieldGrowthPolicy(
QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
self.assistant_model = QComboBox()
self.assistant_model.setEditable(True)
self.assistant_model.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.assistant_model.addItems(ASSISTANT_MODELS)
self.assistant_model.setToolTip(t(
"A name like “sonnet” always means the newest model of that line. "
@@ -1064,9 +1067,10 @@ class SettingsWindow(QDialog):
self.codex_box = QGroupBox(t("Codex"))
codex_form = QFormLayout(self.codex_box)
codex_form.setFieldGrowthPolicy(
QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
self.assistant_codex_model = QComboBox()
self.assistant_codex_model.setEditable(True)
self.assistant_codex_model.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.assistant_codex_model.addItem(t("Codex's own default"), "")
for name in CODEX_MODELS:
self.assistant_codex_model.addItem(name, name)
@@ -1080,9 +1084,10 @@ class SettingsWindow(QDialog):
self.openrouter_box = QGroupBox("OpenRouter")
or_form = QFormLayout(self.openrouter_box)
or_form.setFieldGrowthPolicy(
QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
self.assistant_openrouter_model = QComboBox()
self.assistant_openrouter_model.setEditable(True)
self.assistant_openrouter_model.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.assistant_openrouter_model.addItems(ASSISTANT_OR_MODELS)
or_form.addRow(t("Model"), self.assistant_openrouter_model)
or_note = QLabel(t(
@@ -1228,9 +1233,10 @@ class SettingsWindow(QDialog):
models = QGroupBox(t("Minutes"))
models_form = QFormLayout(models)
models_form.setFieldGrowthPolicy(
QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
self.meeting_model = QComboBox()
self.meeting_model.setEditable(True)
self.meeting_model.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
self.meeting_model.addItems(MEETING_MODELS)
models_form.addRow(t("Model"), self.meeting_model)
self.meeting_reasoning = QComboBox()
@@ -1411,6 +1417,8 @@ class SettingsWindow(QDialog):
# and two combination boxes starting at different places read as two
# unrelated settings rather than the pair they are.
form = QFormLayout()
form.setFieldGrowthPolicy(
QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
self._shortcut_row(
form, "toggle", t("Start and stop"),
t("No global shortcut installed."), placeholder="Ctrl+Space",
@@ -1561,7 +1569,6 @@ class SettingsWindow(QDialog):
"""The field a global shortcut is typed or picked in."""
box = QComboBox()
box.setEditable(True)
box.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
box.addItems(MAC_SHORTCUTS if hotkey.backend() == hotkey.MACOS
else SHORTCUTS)
box.setCurrentText("")
+52 -1
View File
@@ -12,7 +12,7 @@ import unittest
from typing import ClassVar
from unittest import mock
from PyQt6.QtCore import QPoint, QPointF, Qt
from PyQt6.QtCore import QPoint, QPointF, QRect, Qt
from PyQt6.QtGui import QWheelEvent
from PyQt6.QtWidgets import QApplication, QMessageBox
@@ -271,6 +271,46 @@ class Settings(DikteTest):
self.assertEqual(shown, [provider])
self.assertFalse(box.isHidden())
def test_editable_boxes_live_in_forms_that_grow_the_field_column(self):
window = self.window(cfg.Config())
def contains(layout, target):
for index in range(layout.count()):
item = layout.itemAt(index)
widget = item.widget()
if widget is target or (widget is not None and
widget.isAncestorOf(target)):
return True
child = item.layout()
if child is not None and contains(child, target):
return True
return False
forms = window.findChildren(settings_ui.QFormLayout)
boxes = [
window.paste_shortcut,
window.transcribe_model,
window.cleanup_model,
window.cleanup_claude_model,
window.cleanup_codex_model,
window.assistant_model,
window.assistant_codex_model,
window.assistant_openrouter_model,
window.meeting_model,
window.local_llm.repo,
*(box for box, _status, _missing in
window._shortcut_rows.values()),
]
for box in boxes:
form = next((candidate for candidate in forms
if contains(candidate, box)), None)
with self.subTest(box=box.objectName() or box.currentText()):
self.assertIsNotNone(form)
self.assertEqual(
form.fieldGrowthPolicy(),
settings_ui.QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow,
)
def test_codex_answering_refills_both_of_its_boxes(self):
"""The list Codex gave replaces the built-in one, in both places, and
neither loses what was already picked."""
@@ -941,6 +981,17 @@ class Overlay(DikteTest):
widget.show_recording()
widget._reposition()
def test_a_live_indicator_follows_the_cursor_to_another_screen(self):
widget = self.overlay(corner="top-left")
widget.show_recording()
other_screen = mock.Mock()
other_screen.availableGeometry.return_value = QRect(1000, 200, 800, 600)
with mock.patch.object(QApplication, "screenAt",
return_value=other_screen):
widget._tick()
self.assertEqual(widget.pos(), QPoint(1000 + overlay_module.MARGIN,
200 + overlay_module.MARGIN))
def test_a_warning_and_an_error_both_show(self):
widget = self.overlay()
widget.show_warning("cleanup failed")