Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
130 commits
Select commit Hold shift + click to select a range
74c0527
add todo
emcek Nov 2, 2021
26a6d70
change F-16 bios values agains new BIOS
emcek Nov 29, 2021
056ffb2
add callback key to BIOS_VALUE dict
emcek Nov 29, 2021
9385119
load callback method when setting callback in BIOS parser buffer
emcek Nov 29, 2021
18d7a33
refactor start_led_pulse into more general start_led_effect with DCS-…
emcek Nov 29, 2021
b712fc9
add general `led_handler` method
emcek Nov 30, 2021
ff9267c
Merge branch 'master' into led_support
emcek Nov 30, 2021
11e6b78
add SC_MASTER_CAUTION_LED for Ka-50
emcek Nov 30, 2021
3b670d9
update typing
emcek Nov 30, 2021
1a96d27
ignore type for led_event
emcek Nov 30, 2021
fd5b266
typo in docstring
emcek Nov 30, 2021
12eb99b
Merge branch 'master' into led_support
emcek Nov 30, 2021
3e89fab
use red color
emcek Nov 30, 2021
2771ed0
try split effect code
emcek Nov 30, 2021
5659df0
use NamedTuple ti describe effect info
emcek Nov 30, 2021
3e15162
rename namedtuple
emcek Nov 30, 2021
457878c
rename variable
emcek Nov 30, 2021
46fde58
update type
emcek Nov 30, 2021
d07bfdf
longer lines
emcek Nov 30, 2021
9f7465c
remove event and sleep time form LED
emcek Jan 1, 2022
5de5310
temporary solution of working led - use only BIOS_DATA
emcek Jan 1, 2022
e06e05e
try one common BIOS_DATA
emcek Jan 2, 2022
000ffe2
add callback_args
emcek Jan 2, 2022
4900dce
shortcut
emcek Jan 2, 2022
a7bd7b7
fix load_new_plane and callback_args
emcek Jan 2, 2022
8b251d6
use new callback settings
emcek Jan 2, 2022
6e7e061
split DATA and PROTO settings
emcek Jan 2, 2022
40532ec
typo
emcek Jan 2, 2022
cd88030
repr cause inifinity recursion
emcek Jan 2, 2022
d4b445f
Merge branch 'master' into led_support
emcek Jan 2, 2022
ca08575
workaround infinity recession loop
emcek Jan 2, 2022
2346465
width in repr
emcek Jan 2, 2022
c76fa3a
back to getattr
emcek Jan 2, 2022
4bee4e3
split proto and data
emcek Jan 2, 2022
f19d8a9
keep value for BIOS_DATA
emcek Jan 2, 2022
4762768
fix test form BIOS_PROTO
emcek Jan 2, 2022
51fc9af
parametrize test_start_led_effect
emcek Jan 2, 2022
e0b1739
W291 trailing whitespace
emcek Jan 2, 2022
3f9a6bf
remove default_callback
emcek Jan 2, 2022
4e729f8
remove selector form LED effect
emcek Jan 2, 2022
c2c4d92
update LED effect test
emcek Jan 2, 2022
7c2b4b3
make led_handlr static
emcek Jan 2, 2022
e19a089
Merge branch 'master' into led_support
emcek Jan 3, 2022
94d504f
Merge branch 'master' into led_support
emcek Jan 3, 2022
147018a
back to single BIOS_VALUE
emcek Jan 3, 2022
c37ea0e
use bios_data in logitech
emcek Jan 3, 2022
b5d21ea
revert test
emcek Jan 3, 2022
7c13119
redefine bios types
emcek Jan 3, 2022
67b12d0
remove max_value for DCS-BIOS Buffer instance
emcek Jan 4, 2022
6df0944
redefine BIOS type
emcek Jan 4, 2022
4ddcc3f
move mypy to style section
emcek Jan 3, 2022
1cdc9c3
config flake8 and pylint
emcek Jan 4, 2022
60d8086
config flake8 and pylint part 2
emcek Jan 4, 2022
6e80589
remove extra space
emcek Jan 4, 2022
8e4a245
draft of kind of stack
emcek Jan 6, 2022
fd78a09
update comment
emcek Jan 6, 2022
9fd0b33
remove logger
emcek Jan 7, 2022
a74b9bb
basic led_stack handling
emcek Jan 7, 2022
5e409a3
remove import
emcek Jan 7, 2022
9f324a8
sleep after shutdown
emcek Jan 7, 2022
9e6d2c7
keep value with effect and shutdown always before effect take place
emcek Jan 7, 2022
9b3f744
update UML classes
emcek Jan 7, 2022
4ce39e3
update docs
emcek Jan 7, 2022
74b2add
save value in led_handler and remove form led_stack
emcek Jan 7, 2022
f02cf8f
add one basic test for led_handler
emcek Jan 7, 2022
804adbb
cast value to str
emcek Jan 7, 2022
ea56a5e
add new selector to shark
emcek Jan 7, 2022
dbea36c
add new test
emcek Jan 7, 2022
e92dff5
keep only one test
emcek Jan 7, 2022
971d227
remove comment
emcek Jan 7, 2022
bcbb5d7
add test led_effect with two selector
emcek Jan 7, 2022
b6c5252
keep code for testing
emcek Jan 7, 2022
13a8402
led_handler working only with IntegerBuffer
emcek Jan 7, 2022
611ef76
update classes UML
emcek Jan 7, 2022
66c084b
update decumentation
emcek Jan 7, 2022
dba694a
Merge branch 'master' into led_support
emcek Jan 7, 2022
6cc0030
add parameter to config
emcek Jan 8, 2022
1405c22
update defaults values
emcek Jan 8, 2022
9a9d766
run led_handler only when config value is true
emcek Jan 8, 2022
b5a097e
use load_cfg insted config
emcek Jan 8, 2022
4a5e548
add MASTER_CAUTION LED BIOS to all planes
emcek Jan 9, 2022
420f3c2
temp workaround for blink led issue - skip 2 tests
emcek Jan 10, 2022
a8b8ac7
Merge branch 'master' into led_support
emcek Sep 1, 2022
2d1238e
Merge branch 'master' into led_support
emcek Sep 1, 2022
bbd611e
update BIOS data
emcek Sep 1, 2022
dfec465
update BIOS_VALUE type
emcek Sep 1, 2022
bf03498
change 'max_value' key
emcek Sep 1, 2022
3be4441
remove key duplication
emcek Sep 1, 2022
bf94b9a
Merge branch 'master' into led_support
emcek Sep 1, 2022
e0ae92b
disable django
emcek Sep 1, 2022
0658970
Merge branch 'master' into led_support
emcek Jan 27, 2024
1316e49
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 27, 2024
6835013
Refactor LED SDK module import statements and constants usage
emcek Jan 28, 2024
eec1f2e
Merge branch 'master' into led_support
emcek Jan 29, 2024
0f9aba5
add led module for to test
emcek Feb 1, 2024
14f6375
Merge branch 'master' into led_support
emcek Aug 8, 2025
9392cdc
re-add led effect namedtuple
emcek Aug 8, 2025
a3effd7
fir extra/test script led
emcek Aug 8, 2025
d20fb93
dirty fix for aircraft
emcek Aug 8, 2025
4e3f8c2
small alignment in aircraft
emcek Aug 9, 2025
1d7f728
just fix mypy before start development again
emcek Aug 9, 2025
7f072a2
Merge branch 'master' into led_support
emcek Aug 9, 2025
83f1763
move EffectInfo to models and change into pydantic BaseModel
emcek Aug 9, 2025
2b5691b
improve imports in aircraft module
emcek Aug 9, 2025
1bbec13
Merge branch 'master' into led_support
emcek Aug 9, 2025
c3f4f2c
remove led not needed anymore
emcek Aug 15, 2025
26a5040
update led models and LogitechDeviceModel
emcek Aug 15, 2025
ef2a3b8
refactor led_sdk module into LedSdkManager
emcek Aug 15, 2025
e1ef979
update and fix LedSdkManager UT
emcek Aug 15, 2025
31e87fe
quick fix usage LedSdkManager in aircraft module
emcek Aug 15, 2025
c60ca90
quick test of Led handling in GUI
emcek Aug 15, 2025
80f0816
add quick and dirty new tag in GUI for led testing
emcek Aug 15, 2025
a21c2d6
add todo items
emcek Aug 15, 2025
6c77ab5
looks like name in led ska is needed
emcek Aug 17, 2025
4d90ac1
Merge branch 'master' into led_support
emcek Aug 17, 2025
2230f82
update pre-commit config
emcek Aug 19, 2025
fc190e7
Merge remote-tracking branch 'origin/led_support' into led_support
emcek Aug 21, 2025
171ccb1
Merge branch 'master' into led_support
emcek Aug 21, 2025
caf70d3
change imports in aircraft module
emcek Aug 22, 2025
2c48c83
change PIL import in aircraft module
emcek Aug 22, 2025
8f8cb9a
kind of revert of import changes
emcek Aug 22, 2025
4def7f9
Merge branch 'master' into led_support
emcek Aug 25, 2025
ed95b7c
fix isort
emcek Aug 25, 2025
b5ce13c
update changelog
emcek Aug 26, 2025
5079f20
update pre-commit configuration
emcek Aug 26, 2025
2153ec2
update UML with latest changes in LedSdk Manager
emcek Aug 26, 2025
5a9d56d
Merge branch 'master' into led_support
emcek Aug 26, 2025
cce671a
Merge branch 'master' into led_support
emcek Sep 7, 2025
6baa6ad
Merge branch 'master' into led_support
emcek Sep 16, 2025
6b40a6c
organize imports in aircarft module
emcek Sep 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 49 additions & 2 deletions src/dcspy/aircraft.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from __future__ import annotations

from collections import OrderedDict
from collections.abc import Sequence
from itertools import cycle
from logging import getLogger
from pathlib import Path
from pprint import pformat
from re import search
from tempfile import gettempdir
from threading import Timer
from typing import ClassVar

try:
Expand All @@ -17,10 +19,14 @@
from PIL import Image, ImageDraw, ImageFont

from dcspy import default_yaml, load_yaml
from dcspy.models import (DEFAULT_FONT_NAME, NO_OF_LCD_SCREENSHOTS, AircraftKwargs, AnyButton, ApacheAllDrawModesKwargs, ApacheEufdMode, BiosValue, LcdButton,
LcdInfo, RequestModel, RequestType)
from dcspy.models import (DEFAULT_FONT_NAME, NO_OF_LCD_SCREENSHOTS, AircraftKwargs, AnyButton, ApacheAllDrawModesKwargs, ApacheEufdMode, BiosValue, EffectInfo,
LcdButton, LcdInfo, LedEffectType, LedSupport, RequestModel, RequestType)
from dcspy.sdk.led_sdk import LedSdkManager
from dcspy.utils import KeyRequest, replace_symbols, substitute_symbols

# todo: to be removed
RED_PULSE = EffectInfo(type=LedEffectType.PULSE, rgb=(100, 0, 0), duration=0, interval=10)
YELLOW_PULSE = EffectInfo(type=LedEffectType.PULSE, rgb=(100, 100, 0), duration=0, interval=10)
LOG = getLogger(__name__)


Expand Down Expand Up @@ -63,6 +69,11 @@ def __init__(self, lcd_type: LcdInfo) -> None:
self.lcd = lcd_type
self.cfg = load_yaml(full_path=default_yaml)
self.bios_data: dict[str, BiosValue] = {}
self.led = LedSdkManager(target_dev=LedSupport.LOGI_DEVICETYPE_RGB) # todo: do we need copy it here?
self.led_stack: dict[str, EffectInfo] = OrderedDict()
self.led_effect = True
self.led_counter = 16
self.led_shutdown = Timer(3.2, self.led.logi_led_shutdown)
if self.bios_name:
self.key_req = KeyRequest(yaml_path=default_yaml.parent / f'{self.bios_name}.yaml', get_bios_fn=self.get_bios)
self.bios_data.update(self.key_req.cycle_button_ctrl_name)
Expand Down Expand Up @@ -101,6 +112,42 @@ def get_bios(self, selector: str, default: BiosValue = '') -> BiosValue:
except (KeyError, ValueError):
return default

def led_handler(self, selector: str, value: int, effect: EffectInfo) -> None:
"""
Switch on and off LED effect for DCS-BIOS selector.

:param selector:
:param value:
:param effect:
"""
self.bios_data[selector] = value
if self.led_effect and not self.led_counter:
if value:
LOG.debug(f'LED on {selector} val: {value} with {effect}')
self.led.logi_led_shutdown()
self.led_counter = 16
LOG.debug(f'Th: {self.led_shutdown}')
self.led_shutdown = Timer(3.2, self.led.logi_led_shutdown)
self.led_shutdown.start()
self.led.start_led_effect(effect=effect)
self.led_stack[selector] = effect
else:
LOG.debug(f'LED off {selector}')
self._popitem_and_reply_last_effect(selector)
else:
self.led_counter -= 1
LOG.debug(f'Couter: {value} {self.led_counter}')

def _popitem_and_reply_last_effect(self, selector: str) -> None:
del self.led_stack[selector]
if self.led_stack:
selector, effect = self.led_stack.popitem()
LOG.debug(f'Replay effect for {selector}')
value = int(self.bios_data[selector])
self.led_handler(selector, value, effect)
else:
self.led.logi_led_shutdown()

def __repr__(self) -> str:
return f'{super().__repr__()} with: {pformat(self.__dict__)}'

Expand Down
87 changes: 61 additions & 26 deletions src/dcspy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -641,13 +641,33 @@ def make_empty(cls) -> GuiPlaneInputRequest:
return cls(identifier='', request='', widget_iface='')


class LedConstants(Enum):
"""LED constants."""
LOGI_LED_DURATION_INFINITE = 0
class LedSupport(Enum):
"""LED supported types."""
LOGI_DEVICETYPE_NONE = 0
LOGI_DEVICETYPE_MONOCHROME = 1
LOGI_DEVICETYPE_RGB = 2
LOGI_DEVICETYPE_ALL = 3 # LOGI_DEVICETYPE_MONOCHROME | LOGI_DEVICETYPE_RGB

def __str__(self) -> str:
return self.name.split('_')[-1]


class LedEffectType(Enum):
"""LED effect type."""
FLASH = 'flash'
PULSE = 'pulse'
NONE = 'none'

def __str__(self) -> str:
return self.value

# todo: rename it
class EffectInfo(BaseModel):
type: LedEffectType
rgb: tuple[int, int, int] # todo: think of conversion 0-255 -> 0-100% where to do it?
duration: int
interval: int


class LcdButton(Enum):
"""LCD Buttons."""
Expand Down Expand Up @@ -870,6 +890,8 @@ class LogitechDeviceModel(BaseModel):
btn_m_range: tuple[int, int] = (0, 0)
lcd_keys: Sequence[LcdButton] = ()
lcd_info: LcdInfo = NoneLcd
led_type: LedSupport = LedSupport.LOGI_DEVICETYPE_NONE
comments: str = ''

def get_key_at(self, row: int, col: int) -> AnyButton | None:
"""
Expand Down Expand Up @@ -919,17 +941,15 @@ def cols(self) -> int:
return max([self.no_g_modes, mouse_btn_exist, lcd_btn_exists])

def __str__(self) -> str:
result = []
if self.lcd_info.type.value:
result.append(f'{self.lcd_info}')
if self.lcd_keys:
lcd_buttons = ', '.join([str(lcd_btn) for lcd_btn in self.lcd_keys])
result.append(f'LCD Buttons: {lcd_buttons}')
if self.no_g_modes and self.no_g_keys:
result.append(f'G-Keys: {self.no_g_keys} in {self.no_g_modes} modes')
if self.btn_m_range[0] and self.btn_m_range[1]:
result.append(f'Mouse Buttons: {self.btn_m_range[0]} to {self.btn_m_range[1]}')
return '\n'.join(result)
details = [
str(self.lcd_info) if self.lcd_info.type.value else None,
f"LCD Buttons: {', '.join(map(str, self.lcd_keys))}" if self.lcd_keys else None,
f"G-Keys: {self.no_g_keys} in {self.no_g_modes} modes" if self.no_g_modes and self.no_g_keys else None,
f"Mouse Buttons: {self.btn_m_range[0]} to {self.btn_m_range[1]}" if all(self.btn_m_range) else None,
f"LED support: {self.led_type}" if self.led_type.value else None, # todo: test this
f"Comments: {self.comments}" if self.comments else None, # todo: test this
]
return '\n'.join(filter(None, details))

@property
def g_keys(self) -> Sequence[Gkey]:
Expand Down Expand Up @@ -960,23 +980,37 @@ def lcd_name(self) -> str:


G19 = LogitechDeviceModel(klass='G19', no_g_modes=3, no_g_keys=12, lcd_info=LcdColor,
lcd_keys=(LcdButton.LEFT, LcdButton.RIGHT, LcdButton.OK, LcdButton.CANCEL, LcdButton.UP, LcdButton.DOWN, LcdButton.MENU))
lcd_keys=(LcdButton.LEFT, LcdButton.RIGHT, LcdButton.OK, LcdButton.CANCEL, LcdButton.UP, LcdButton.DOWN, LcdButton.MENU),
led_type=LedSupport.LOGI_DEVICETYPE_RGB)
G13 = LogitechDeviceModel(klass='G13', no_g_modes=3, no_g_keys=29, lcd_info=LcdMono,
lcd_keys=(LcdButton.ONE, LcdButton.TWO, LcdButton.THREE, LcdButton.FOUR))
lcd_keys=(LcdButton.ONE, LcdButton.TWO, LcdButton.THREE, LcdButton.FOUR),
led_type=LedSupport.LOGI_DEVICETYPE_RGB)
G15v1 = LogitechDeviceModel(klass='G15v1', no_g_modes=3, no_g_keys=18, lcd_info=LcdMono,
lcd_keys=(LcdButton.ONE, LcdButton.TWO, LcdButton.THREE, LcdButton.FOUR))
lcd_keys=(LcdButton.ONE, LcdButton.TWO, LcdButton.THREE, LcdButton.FOUR),
led_type=LedSupport.LOGI_DEVICETYPE_MONOCHROME,
comments='Highest RGB given is <33%, the color will be off, if >33% and <66%, the '
'brightness will be low, and when >66%, the brightness will be high') # todo: make nicer descriptions
G15v2 = LogitechDeviceModel(klass='G15v2', no_g_modes=3, no_g_keys=6, lcd_info=LcdMono,
lcd_keys=(LcdButton.ONE, LcdButton.TWO, LcdButton.THREE, LcdButton.FOUR))
lcd_keys=(LcdButton.ONE, LcdButton.TWO, LcdButton.THREE, LcdButton.FOUR),
led_type=LedSupport.LOGI_DEVICETYPE_MONOCHROME,
comments='Highest RGB given is <33%, the color will be off, if >33% and <66%, the '
'brightness will be low, and when >66%, the brightness will be high')
G510 = LogitechDeviceModel(klass='G510', no_g_modes=3, no_g_keys=18, lcd_info=LcdMono,
lcd_keys=(LcdButton.ONE, LcdButton.TWO, LcdButton.THREE, LcdButton.FOUR))
lcd_keys=(LcdButton.ONE, LcdButton.TWO, LcdButton.THREE, LcdButton.FOUR),
led_type=LedSupport.LOGI_DEVICETYPE_RGB)
LCD_KEYBOARDS_DEV = [G19, G510, G15v1, G15v2, G13]

G910 = LogitechDeviceModel(klass='G910', no_g_modes=3, no_g_keys=9)
G710 = LogitechDeviceModel(klass='G710', no_g_modes=3, no_g_keys=6)
G110 = LogitechDeviceModel(klass='G110', no_g_modes=3, no_g_keys=12)
G910 = LogitechDeviceModel(klass='G910', no_g_modes=3, no_g_keys=9, led_type=LedSupport.LOGI_DEVICETYPE_RGB)
G710 = LogitechDeviceModel(klass='G710', no_g_modes=3, no_g_keys=6, led_type=LedSupport.LOGI_DEVICETYPE_MONOCHROME,
comments='Highest value for R, G or B defines brightness')
G110 = LogitechDeviceModel(klass='G110', no_g_modes=3, no_g_keys=12, led_type=LedSupport.LOGI_DEVICETYPE_RGB,
comments='green it will be ignored')
G103 = LogitechDeviceModel(klass='G103', no_g_modes=3, no_g_keys=6)
G105 = LogitechDeviceModel(klass='G105', no_g_modes=3, no_g_keys=6)
G11 = LogitechDeviceModel(klass='G11', no_g_modes=3, no_g_keys=18)
G105 = LogitechDeviceModel(klass='G105', no_g_modes=3, no_g_keys=6, led_type=LedSupport.LOGI_DEVICETYPE_MONOCHROME,
comments='Highest value for R, G or B defines brightness')
G11 = LogitechDeviceModel(klass='G11', no_g_modes=3, no_g_keys=18, led_type=LedSupport.LOGI_DEVICETYPE_MONOCHROME,
comments='Highest RGB given is <33%, the color will be off, if >33% and <66%, the brightness '
'will be low, and when >66%, the brightness will be high')
KEYBOARDS_DEV = [G910, G710, G110, G103, G105, G11]

G35 = LogitechDeviceModel(klass='G35', no_g_modes=1, no_g_keys=3)
Expand All @@ -985,8 +1019,9 @@ def lcd_name(self) -> str:
G933 = LogitechDeviceModel(klass='G933', no_g_modes=1, no_g_keys=3)
HEADPHONES_DEV = [G35, G633, G930, G933]

G600 = LogitechDeviceModel(klass='G600', btn_m_range=(6, 20))
G300 = LogitechDeviceModel(klass='G300', btn_m_range=(6, 9))
G600 = LogitechDeviceModel(klass='G600', btn_m_range=(6, 20), led_type=LedSupport.LOGI_DEVICETYPE_RGB)
G300 = LogitechDeviceModel(klass='G300', btn_m_range=(6, 9), led_type=LedSupport.LOGI_DEVICETYPE_RGB,
comments='When calling the LED, if <50%, the color will be off, and when >50%, the color will be on')
G400 = LogitechDeviceModel(klass='G400', btn_m_range=(6, 8))
G700 = LogitechDeviceModel(klass='G700', btn_m_range=(1, 13))
G9 = LogitechDeviceModel(klass='G9', btn_m_range=(4, 8))
Expand Down
60 changes: 55 additions & 5 deletions src/dcspy/qt_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@
from PySide6.QtGui import (QAction, QActionGroup, QColor, QColorConstants, QFont, QGuiApplication, QIcon, QPixmap, QShowEvent, QStandardItemModel, QStyleHints,
QTextCharFormat)
from PySide6.QtUiTools import QUiLoader
from PySide6.QtWidgets import (QApplication, QButtonGroup, QCheckBox, QComboBox, QCompleter, QDialog, QDockWidget, QFileDialog, QGroupBox, QLabel, QLineEdit,
QListView, QMainWindow, QMenu, QMessageBox, QProgressBar, QPushButton, QRadioButton, QSlider, QSpinBox, QStatusBar,
QSystemTrayIcon, QTableWidget, QTabWidget, QTextBrowser, QTextEdit, QToolBar, QToolBox, QWidget)
from PySide6.QtWidgets import (QApplication, QButtonGroup, QCheckBox, QComboBox, QCompleter, QDialog, QDockWidget, QDoubleSpinBox, QFileDialog, QGroupBox,
QLabel, QLineEdit, QListView, QMainWindow, QMenu, QMessageBox, QProgressBar, QPushButton, QRadioButton, QSlider, QSpinBox,
QStatusBar, QSystemTrayIcon, QTableWidget, QTabWidget, QTextBrowser, QTextEdit, QToolBar, QToolBox, QWidget)

from dcspy import default_yaml, qtgui_rc
from dcspy.models import (ALL_DEV, BIOS_REPO_NAME, CTRL_LIST_SEPARATOR, DCSPY_REPO_NAME, AnyButton, ControlDepiction, ControlKeyData, DcspyConfigYaml,
FontsConfig, Gkey, GuiPlaneInputRequest, GuiTab, LcdButton, LcdMono, LcdType, LogitechDeviceModel, MouseButton, MsgBoxTypes, Release,
RequestType, SystemData, __version__)
EffectInfo, FontsConfig, Gkey, GuiPlaneInputRequest, GuiTab, LcdButton, LcdMono, LcdType, LedEffectType, LedSupport,
LogitechDeviceModel, MouseButton, MsgBoxTypes, Release, RequestType, SystemData, __version__)
from dcspy.sdk.led_sdk import LedSdkManager
from dcspy.starter import DCSpyStarter
from dcspy.utils import (CloneProgress, check_bios_ver, check_dcs_bios_entry, check_dcs_ver, check_github_repo, check_ver_at_github, collect_debug_data,
count_files, defaults_cfg, detect_system_color_mode, download_file, generate_bios_jsons_with_lupa, get_all_git_refs,
Expand Down Expand Up @@ -61,6 +62,7 @@ def __init__(self, cli_args=Namespace(), cfg_dict: DcspyConfigYaml | None = None
"""
super().__init__()
UiLoader().load_ui(':/ui/ui/qtdcs.ui', self)
self.led = LedSdkManager(name='DCSpy', target_dev=LedSupport.LOGI_DEVICETYPE_RGB) # todo: where to keep it for simulation purpose
self._find_children()
self.config = cfg_dict
if not cfg_dict:
Expand Down Expand Up @@ -92,12 +94,14 @@ def __init__(self, cli_args=Namespace(), cfg_dict: DcspyConfigYaml | None = None
self.dw_device.setFloating(True)
self.bg_rb_input_iface = QButtonGroup(self)
self.bg_rb_device = QButtonGroup(self)
self.led_effect = EffectInfo(type=LedEffectType.NONE, rgb=(0,0,0), duration=0, interval=0)
self._init_tray()
self._init_combo_plane()
self._init_menu_bar()
self.apply_configuration(cfg=self.config)
self._init_settings()
self._init_devices()
self._init_led()
self._init_autosave()
self._trigger_refresh_data()

Expand Down Expand Up @@ -236,6 +240,39 @@ def _init_menu_bar(self) -> None:
color_mode.addAction(self.a_mode_system)
color_mode.triggered.connect(self._switch_color_mode)

def _init_led(self) -> None:
"""Initialize LED related stuff."""
self.combo_effect_type.addItems([LedEffectType.PULSE.name, LedEffectType.FLASH.name])

self.pb_stop_sim.clicked.connect(self._stop_led)
self.pb_start_sim.clicked.connect(self._start_led)
self.sp_interval.valueChanged.connect(self._set_led_effect)
self.sp_duration.valueChanged.connect(self._set_led_effect)
self.sp_sleep.valueChanged.connect(self._set_led_effect)
self.sp_r.valueChanged.connect(self._set_led_effect)
self.sp_g.valueChanged.connect(self._set_led_effect)
self.sp_b.valueChanged.connect(self._set_led_effect)
self.combo_effect_type.currentIndexChanged.connect(self._set_led_effect)


def _set_led_effect(self) -> None:
"""Set LED effect."""
# todo: how to save it in a config file
self.led_effect = EffectInfo(type=getattr(LedEffectType, self.combo_effect_type.currentText()),
rgb=(int(self.sp_r.value()), int(self.sp_g.value()), int(self.sp_b.value())),
duration=self.sp_duration.value(), interval=self.sp_interval.value())

def _start_led(self):
self.led.logi_led_init()
self.led.logi_led_set_target_device(LedSupport.LOGI_DEVICETYPE_RGB) # todo: take from device
LOG.debug(f'Start LED effect: {self.led_effect}')
self.led.start_led_effect(effect=self.led_effect)

def _stop_led(self):
self.led.logi_led_stop_effects()
LOG.debug('Stopped LED effect')
self.led.logi_led_shutdown()

def _init_autosave(self) -> None:
"""Initialize of autosave."""
widget_dict = {
Expand Down Expand Up @@ -458,6 +495,7 @@ def _load_table_gkeys(self) -> None:
def _generate_table(self) -> None:
"""Generate a table of combo boxes with completer functionality."""
ctrl_list_without_sep = [item for item in self.ctrl_list if item and CTRL_LIST_SEPARATOR not in item]
self.combo_ctrl.addItems(self.ctrl_list) # todo: move to better place
for row in range(0, self.device.rows.total):
for col in range(0, self.device.cols):
self._make_combo_with_completer_at(row, col, ctrl_list_without_sep)
Expand Down Expand Up @@ -1744,6 +1782,18 @@ def _find_children(self) -> None:
self.pb_bios_check: QPushButton = self.findChild(QPushButton, 'pb_bios_check') # type: ignore[assignment]
self.pb_bios_repair: QPushButton = self.findChild(QPushButton, 'pb_bios_repair') # type: ignore[assignment]

# todo: move to correct places, change widgets types
self.pb_stop_sim: QPushButton = self.findChild(QPushButton, 'pb_stop_sim') # type: ignore[assignment]
self.pb_start_sim: QPushButton = self.findChild(QPushButton, 'pb_start_sim') # type: ignore[assignment]
self.combo_ctrl: QComboBox = self.findChild(QComboBox, 'combo_ctrl') # type: ignore[assignment]
self.combo_effect_type: QComboBox = self.findChild(QComboBox, 'combo_effect_type') # type: ignore[assignment]
self.sp_interval: QSpinBox = self.findChild(QSpinBox, 'sp_interval') # type: ignore[assignment]
self.sp_duration: QSpinBox = self.findChild(QSpinBox, 'sp_duration') # type: ignore[assignment]
self.sp_sleep: QDoubleSpinBox = self.findChild(QDoubleSpinBox, 'sp_sleep') # type: ignore[assignment]
self.sp_r: QSpinBox = self.findChild(QSpinBox, 'sp_r') # type: ignore[assignment]
self.sp_g: QSpinBox = self.findChild(QSpinBox, 'sp_g') # type: ignore[assignment]
self.sp_b: QSpinBox = self.findChild(QSpinBox, 'sp_b') # type: ignore[assignment]

self.cb_autostart: QCheckBox = self.findChild(QCheckBox, 'cb_autostart') # type: ignore[assignment]
self.cb_show_gui: QCheckBox = self.findChild(QCheckBox, 'cb_show_gui') # type: ignore[assignment]
self.cb_check_ver: QCheckBox = self.findChild(QCheckBox, 'cb_check_ver') # type: ignore[assignment]
Expand Down
Loading
Loading