mirror of
https://github.com/yusufipk/dikte.git
synced 2026-09-11 10:56:10 +00:00
Merge remote-tracking branch 'origin/master' into pr/fix-combobox-and-overlay-multiscreen
# Conflicts: # tests/test_ui.py
This commit is contained in:
+6
-2
@@ -163,11 +163,13 @@ class Dikte:
|
||||
self.front_before = None
|
||||
self._front_watch = None
|
||||
|
||||
self.overlay = Overlay(self.conf["overlay_corner"])
|
||||
self.overlay = Overlay(self.conf["overlay_corner"],
|
||||
screen_name=self.conf["overlay_screen"])
|
||||
# The agent's indicator sits on top of the dictation one when both are
|
||||
# up, and drops into the corner when it is alone there.
|
||||
self.ask_overlay = Overlay(self.conf["overlay_corner"], below=self.overlay,
|
||||
dismissable=True)
|
||||
dismissable=True,
|
||||
screen_name=self.conf["overlay_screen"])
|
||||
self.recorder = audio.Recorder()
|
||||
self.pipeline = Pipeline(self.conf)
|
||||
self.ask_pipeline = Pipeline(self.conf)
|
||||
@@ -1296,7 +1298,9 @@ class Dikte:
|
||||
|
||||
def _apply_settings(self):
|
||||
self.overlay.corner = self.conf["overlay_corner"]
|
||||
self.overlay.screen_name = self.conf["overlay_screen"]
|
||||
self.ask_overlay.corner = self.conf["overlay_corner"]
|
||||
self.ask_overlay.screen_name = self.conf["overlay_screen"]
|
||||
self._apply_local()
|
||||
self._build_tray()
|
||||
self._refresh_tray()
|
||||
|
||||
@@ -457,6 +457,7 @@ DEFAULTS = {
|
||||
"pause_shortcut": "",
|
||||
"evdev_hotkey": False,
|
||||
"overlay_corner": "bottom-left",
|
||||
"overlay_screen": "",
|
||||
"keep_audio": False,
|
||||
"history_limit": 200,
|
||||
# A look at the releases page once a day, and nothing more than a look:
|
||||
|
||||
@@ -151,6 +151,7 @@ TR = {
|
||||
# --- settings: tabs and general ------------------------------------
|
||||
"Dikte Settings": "Dikte Ayarları",
|
||||
"General": "Genel",
|
||||
"Display": "Ekran",
|
||||
"API and models": "API ve modeller",
|
||||
"Cleanup rules": "Temizleme kuralları",
|
||||
"Audio file": "Ses dosyası",
|
||||
@@ -179,6 +180,9 @@ TR = {
|
||||
"macOS bu ilk gönderildiğinde Erişilebilirlik izni ister.",
|
||||
"Restore the previous clipboard after pasting":
|
||||
"Yapıştırdıktan sonra eski pano içeriğini geri koy",
|
||||
"Indicator screen": "Gösterge ekranı",
|
||||
"Follow the mouse pointer": "Fare imlecini takip et",
|
||||
"{name} (not connected)": "{name} (bağlı değil)",
|
||||
"Indicator corner": "Gösterge köşesi",
|
||||
"bottom-left": "sol-alt",
|
||||
"bottom-right": "sağ-alt",
|
||||
|
||||
+13
-4
@@ -42,9 +42,11 @@ class Overlay(QWidget):
|
||||
of covering it, which is what lets a dictation and a command to the agent be
|
||||
under way at the same time and still both be visible."""
|
||||
|
||||
def __init__(self, corner="bottom-left", below=None, dismissable=False):
|
||||
def __init__(self, corner="bottom-left", below=None, dismissable=False,
|
||||
screen_name=""):
|
||||
super().__init__(None)
|
||||
self.corner = corner
|
||||
self.screen_name = screen_name
|
||||
self.below = below
|
||||
# A job that can run for ten minutes should not have to be watched for
|
||||
# ten minutes. Clicking such an indicator puts the progress away; the
|
||||
@@ -251,8 +253,15 @@ class Overlay(QWidget):
|
||||
self.resize(width, HEIGHT)
|
||||
|
||||
def _reposition(self):
|
||||
# On a multi-monitor setup, show up where the user actually is.
|
||||
screen = QApplication.screenAt(QCursor.pos()) or QApplication.primaryScreen()
|
||||
# The screen the settings name, or, when none is named or it is not
|
||||
# plugged in right now, where the user actually is. Names are connector
|
||||
# names on X11 and model names on macOS, where two identical monitors
|
||||
# can share one; the first then wins.
|
||||
screen = next(
|
||||
(item for item in QApplication.screens() if item.name() == self.screen_name),
|
||||
None,
|
||||
) if self.screen_name else None
|
||||
screen = screen or QApplication.screenAt(QCursor.pos()) or QApplication.primaryScreen()
|
||||
area = screen.availableGeometry()
|
||||
left = "left" in self.corner
|
||||
top = "top" in self.corner
|
||||
@@ -271,7 +280,7 @@ class Overlay(QWidget):
|
||||
# the corner when it does rather than leaving a gap where it was.
|
||||
if self.below is not None and self.below.showing != self._stacked:
|
||||
self._reposition()
|
||||
elif self.state in LIVE:
|
||||
elif self.state in LIVE and not self.screen_name:
|
||||
current_screen = QApplication.screenAt(QCursor.pos())
|
||||
if current_screen is not None and current_screen != self.screen():
|
||||
self._reposition()
|
||||
|
||||
+31
-5
@@ -596,6 +596,7 @@ class SettingsWindow(QDialog):
|
||||
|
||||
tabs = self.tabs = QTabWidget(self)
|
||||
tabs.addTab(self._scrolled(self._general_tab()), t("General"))
|
||||
tabs.addTab(self._scrolled(self._display_tab()), t("Display"))
|
||||
self.api_tab_index = tabs.addTab(
|
||||
self._scrolled(self._api_tab()), t("API and models"))
|
||||
tabs.addTab(self._scrolled(self._prompt_tab()), t("Cleanup rules"))
|
||||
@@ -718,11 +719,6 @@ class SettingsWindow(QDialog):
|
||||
self.restore_clipboard = QCheckBox(t("Restore the previous clipboard after pasting"))
|
||||
form.addRow("", self.restore_clipboard)
|
||||
|
||||
self.corner = QComboBox()
|
||||
for value in CORNERS:
|
||||
self.corner.addItem(t(value), value)
|
||||
form.addRow(t("Indicator corner"), self.corner)
|
||||
|
||||
self.max_seconds = QSpinBox()
|
||||
self.max_seconds.setRange(10, 3600)
|
||||
self.max_seconds.setSuffix(t(" s"))
|
||||
@@ -773,6 +769,31 @@ class SettingsWindow(QDialog):
|
||||
self.update_now))
|
||||
return page
|
||||
|
||||
def _display_tab(self):
|
||||
page = QWidget()
|
||||
form = QFormLayout(page)
|
||||
|
||||
self.indicator_screen = QComboBox()
|
||||
self.indicator_screen.addItem(t("Follow the mouse pointer"), "")
|
||||
for screen in QGuiApplication.screens():
|
||||
# The native resolution, so that a scaled 4K screen reads
|
||||
# 3840 × 2160 and not the 1920 × 1080 Qt sees through the scale.
|
||||
area = screen.geometry()
|
||||
ratio = screen.devicePixelRatio()
|
||||
self.indicator_screen.addItem(
|
||||
t("{name} ({width} × {height})", name=screen.name(),
|
||||
width=round(area.width() * ratio),
|
||||
height=round(area.height() * ratio)),
|
||||
screen.name(),
|
||||
)
|
||||
form.addRow(t("Indicator screen"), self.indicator_screen)
|
||||
|
||||
self.corner = QComboBox()
|
||||
for value in CORNERS:
|
||||
self.corner.addItem(t(value), value)
|
||||
form.addRow(t("Indicator corner"), self.corner)
|
||||
return page
|
||||
|
||||
def _api_tab(self):
|
||||
page = QWidget()
|
||||
outer = QVBoxLayout(page)
|
||||
@@ -1652,6 +1673,10 @@ class SettingsWindow(QDialog):
|
||||
self.auto_paste.setChecked(conf["auto_paste"])
|
||||
self.paste_shortcut.setCurrentText(conf["paste_shortcut"])
|
||||
self.restore_clipboard.setChecked(conf["restore_clipboard"])
|
||||
screen_name = conf["overlay_screen"]
|
||||
if screen_name and self.indicator_screen.findData(screen_name) < 0:
|
||||
self.indicator_screen.addItem(t("{name} (not connected)", name=screen_name), screen_name)
|
||||
self._select_data(self.indicator_screen, screen_name)
|
||||
self._select_data(self.corner, conf["overlay_corner"])
|
||||
self.max_seconds.setValue(conf["max_seconds"])
|
||||
self.skip_silent.setChecked(conf["skip_silent"])
|
||||
@@ -1759,6 +1784,7 @@ class SettingsWindow(QDialog):
|
||||
conf["auto_paste"] = self.auto_paste.isChecked()
|
||||
conf["paste_shortcut"] = self.paste_shortcut.currentText().strip()
|
||||
conf["restore_clipboard"] = self.restore_clipboard.isChecked()
|
||||
conf["overlay_screen"] = self.indicator_screen.currentData() or ""
|
||||
conf["overlay_corner"] = self.corner.currentData() or "bottom-left"
|
||||
conf["max_seconds"] = self.max_seconds.value()
|
||||
conf["skip_silent"] = self.skip_silent.isChecked()
|
||||
|
||||
+13
-1
@@ -42,6 +42,7 @@ CHANGED = {
|
||||
"paste_shortcut": "ctrl+shift+v",
|
||||
"restore_clipboard": True,
|
||||
"overlay_corner": "top-right",
|
||||
"overlay_screen": "DP-1",
|
||||
"max_seconds": 120,
|
||||
"skip_silent": False,
|
||||
"silence_db": -42.0,
|
||||
@@ -161,7 +162,7 @@ class Settings(DikteTest):
|
||||
def test_the_window_opens_with_every_tab_on_it(self):
|
||||
window = self.window(cfg.Config())
|
||||
tabs = window.findChildren(settings_ui.QTabWidget)[0]
|
||||
self.assertEqual(tabs.count(), 9)
|
||||
self.assertEqual(tabs.count(), 10)
|
||||
self.assertEqual(window.windowTitle(), "Dikte Settings")
|
||||
|
||||
def test_no_tab_can_stretch_the_window_past_a_small_screen(self):
|
||||
@@ -992,6 +993,17 @@ class Overlay(DikteTest):
|
||||
self.assertEqual(widget.pos(), QPoint(1000 + overlay_module.MARGIN,
|
||||
200 + overlay_module.MARGIN))
|
||||
|
||||
def test_a_named_screen_is_used_instead_of_the_pointer_screen(self):
|
||||
screen = mock.Mock()
|
||||
screen.name.return_value = "DP-1"
|
||||
screen.availableGeometry.return_value = settings_ui.QRect(1920, 0, 1920, 1080)
|
||||
widget = self.overlay(screen_name="DP-1")
|
||||
with mock.patch.object(QApplication, "screens", return_value=[screen]), \
|
||||
mock.patch.object(QApplication, "screenAt") as screen_at:
|
||||
widget._reposition()
|
||||
screen_at.assert_not_called()
|
||||
self.assertEqual(widget.pos(), QPoint(1948, 995))
|
||||
|
||||
def test_a_warning_and_an_error_both_show(self):
|
||||
widget = self.overlay()
|
||||
widget.show_warning("cleanup failed")
|
||||
|
||||
Reference in New Issue
Block a user