Keyboard update

This commit is contained in:
Thastertyn committed 2025-04-05 21:53:58 +02:00
1 parent 859bdd19c3
commit bd602a31ea
10 files changed
+610 -208

No files matched your search

+4 -4
View File
@@ -3,9 +3,9 @@ import logging
from PySide6.QtWidgets import QMessageBox, QApplication
from app.utils import setup_logger
from app.ui import window
from app.ui.view import KeyboardView
from app.utils import setup_logger
class Keyboard():
def __init__(self):
@@ -15,7 +15,7 @@ class Keyboard():
self.qt_app = QApplication([])
self.window = window.KeyboardWindow()
self.view = KeyboardView()
def exit_with_error(self, error: str, additional_text: str = ""):
self.show_error(error, additional_text)
@@ -23,7 +23,7 @@ class Keyboard():
sys.exit(1)
def run(self) -> int:
self.window.show()
self.view.show()
status = self.qt_app.exec()
self.cleanup()
self.logger.info("Exiting")
+39 -54
View File
@@ -1,67 +1,52 @@
from PySide6.QtWidgets import QWidget, QLabel, QApplication
from PySide6.QtGui import QPainter, QPen, QColor
from PySide6.QtCore import QRectF, Qt, QSize
import sys
from PySide6.QtWidgets import (
QGraphicsRectItem, QGraphicsSimpleTextItem, QGraphicsItem
)
from PySide6.QtGui import QBrush, QColor, QFont, QFontMetricsF
class KeyWidget(QWidget):
def __init__(self, key_label: str, debug: bool = False, parent=None):
super().__init__(parent)
self.key_label = key_label
self.debug = debug
class KeyItem(QGraphicsRectItem):
def __init__(self, label):
super().__init__()
self.label = label
self.text = QGraphicsSimpleTextItem(label, self)
self.text.setFlag(QGraphicsItem.ItemIgnoresTransformations, True)
self.label = QLabel(key_label, self)
self.label.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.setBrush(QBrush(QColor("lightgray")))
self.hitbox_rect = QRectF(0, 0, 50, 50)
self.resize(60, 60)
self.scale_factor = 1.0
self.width = 0
self.height = 0
def resizeEvent(self, event):
self.label.setGeometry(0, 0, self.width(), self.height())
def set_geometry(self, x, y, width, height):
self.width = width
self.height = height
def paintEvent(self, event):
painter = QPainter(self)
self.setRect(0, 0, width, height)
self.setPos(x, y)
self.setTransformOriginPoint(width / 2, height / 2)
# Always draw the base border (true key bounds)
base_pen = QPen(QColor(100, 100, 100), 1, Qt.SolidLine)
painter.setPen(base_pen)
painter.drawRect(0, 0, self.width() - 1, self.height() - 1)
self.update_label_font()
if self.debug:
# Draw hitbox as red dashed line
hitbox_pen = QPen(QColor(255, 0, 0), 2, Qt.DashLine)
painter.setPen(hitbox_pen)
painter.drawRect(self.hitbox_rect)
def update_label_font(self):
# Dynamically size font
font_size = min(self.width, self.height) * 0.4
font = QFont()
font.setPointSizeF(font_size)
self.text.setFont(font)
def set_hitbox_size(self, width: float, height: float):
x = (self.width() - width) / 2
y = (self.height() - height) / 2
self.hitbox_rect = QRectF(x, y, width, height)
self.update()
# Use font metrics for accurate bounding
metrics = QFontMetricsF(font)
text_rect = metrics.boundingRect(self.label)
def sizeHint(self) -> QSize:
return QSize(60, 60)
text_x = (self.width - text_rect.width()) / 2
text_y = (self.height - text_rect.height()) / 2 # + metrics.ascent() - text_rect.height()
def mousePressEvent(self, event):
if self.hitbox_rect.contains(event.position()):
print(f"Key '{self.key_label}' pressed inside hitbox.")
else:
print(f"Key '{self.key_label}' clicked outside hitbox.")
self.text.setPos(text_x, text_y)
def set_scale_factor(self, scale):
self.scale_factor = scale
self.setZValue(scale)
self.setScale(scale)
if __name__ == "__main__":
app = QApplication(sys.argv)
from PySide6.QtWidgets import QGridLayout, QWidget
main_window = QWidget()
layout = QGridLayout(main_window)
keys = "ASDF"
for i, char in enumerate(keys):
key = KeyWidget(char, debug=True)
key.set_hitbox_size(30 + i * 10, 30 + i * 5) # Varying hitbox sizes
layout.addWidget(key, 0, i)
main_window.show()
sys.exit(app.exec())
def mousePressEvent(self, q_mouse_event):
print(self.label, "was clicked")
+79
View File
@@ -0,0 +1,79 @@
from PySide6.QtWidgets import (
QGraphicsScene
)
from PySide6.QtGui import QBrush, QColor
from PySide6.QtCore import QTimer, QRectF, QSize
import random
from app.ui.key import KeyItem
class KeyboardScene(QGraphicsScene):
def __init__(self):
super().__init__()
self.keys = {}
self.letter_rows = [
"QWERTYUIOP",
"ASDFGHJKL",
"ZXCVBNM",
]
self.space_key = KeyItem("Space")
self.addItem(self.space_key)
self.timer = QTimer()
self.timer.timeout.connect(self.simulate_prediction)
self.timer.start(2000)
self.create_keys()
def create_keys(self):
for row in self.letter_rows:
for char in row:
key = KeyItem(char)
self.addItem(key)
self.keys[char] = key
def layout_keys(self, view_size: QSize):
view_width = view_size.width()
view_height = view_size.height()
padding = 10.0
spacing = 6.0
max_scale = 2.0
rows = self.letter_rows + [" "]
row_count = len(rows)
max_keys_in_row = max(len(row) for row in rows)
total_spacing_x = (max_keys_in_row - 1) * spacing
total_spacing_y = (row_count - 1) * spacing
available_width = view_width - 2 * padding - total_spacing_x
available_height = view_height - 2 * padding - total_spacing_y
key_width = available_width / max_keys_in_row
key_height = available_height / row_count
y = padding
for row in self.letter_rows:
x = padding
for char in row:
key = self.keys[char]
key.set_geometry(x, y, key_width, key_height)
x += key_width + spacing
y += key_height + spacing
# Space key layout
space_width = key_width * 7 + spacing * 6
self.space_key.set_geometry(padding, y, space_width, key_height)
self.setSceneRect(QRectF(0, 0, view_width, view_height))
def simulate_prediction(self):
most_likely = random.choice(list(self.keys.keys()))
print(f"[Prediction] Most likely: {most_likely}")
for char, key in self.keys.items():
if char == most_likely:
key.set_scale_factor(1.8)
key.setBrush(QBrush(QColor("orange")))
else:
key.set_scale_factor(1.0)
key.setBrush(QBrush(QColor("lightgray")))
+21
View File
@@ -0,0 +1,21 @@
from PySide6.QtWidgets import (
QGraphicsView
)
from PySide6.QtGui import QPainter
from PySide6.QtCore import Qt
from .scene import KeyboardScene
class KeyboardView(QGraphicsView):
def __init__(self):
super().__init__()
self.scene = KeyboardScene()
self.setScene(self.scene)
self.setRenderHint(QPainter.Antialiasing)
self.setWindowTitle("Dynamic Keyboard")
self.setAlignment(Qt.AlignLeft | Qt.AlignTop)
self.setMinimumSize(600, 200) # Sensible default
def resizeEvent(self, event):
super().resizeEvent(event)
self.scene.layout_keys(self.viewport().size())
-43
View File
@@ -1,43 +0,0 @@
from PySide6.QtWidgets import QMainWindow, QApplication, QTabWidget
class KeyboardWindow(QMainWindow):
def __init__(self):
super().__init__()
# Set up main window properties
self.setWindowTitle("OMEGA")
self.setGeometry(0, 0, 800, 600)
self.center_window()
# Central widget and layout
central_widget = QTabWidget()
self.setCentralWidget(central_widget)
def center_window(self):
# Get the screen geometry
screen = QApplication.primaryScreen()
screen_geometry = screen.geometry()
# Get the dimensions of the window
window_geometry = self.frameGeometry()
# Calculate the center point of the screen
center_point = screen_geometry.center()
# Move the window geometry to the center of the screen
window_geometry.moveCenter(center_point)
# Move the window to the calculated geometry
self.move(window_geometry.topLeft())
def refresh_book_cards(self):
self.dashboard.redraw_cards()
self.category_statistics_overview_list.redraw_cards()
def refresh_member_cards(self):
self.member_list.redraw_cards()
+27 -1
View File
@@ -24,4 +24,30 @@ def setup_logger():
formatter = logging.Formatter("[%(levelname)s] - %(name)s:%(lineno)d - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.addHandler(handler)
if sys.platform == "win32":
import win32con
import win32gui
import win32api
import win32process
def make_window_non_activating(win):
hwnd = int(win.winId())
ex_style = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
# Add styles
ex_style |= win32con.WS_EX_NOACTIVATE
ex_style |= win32con.WS_EX_TOPMOST
ex_style |= win32con.WS_EX_TOOLWINDOW # optional: hide from Alt+Tab
win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, ex_style)
# Force update
win32gui.SetWindowPos(
hwnd, win32con.HWND_TOPMOST,
0, 0, 0, 0,
win32con.SWP_NOMOVE | win32con.SWP_NOSIZE | win32con.SWP_NOACTIVATE
)