testy custom qtdragon zakladka, brak powodzenia

This commit is contained in:
2025-12-12 15:59:58 +01:00
parent fac64313c5
commit a1895c9d37
8 changed files with 18510 additions and 9 deletions

View File

@@ -1,3 +1,6 @@
# Include your custom_postgui HAL commands here
# This file will not be overwritten when you run stepconf again
# Plik: custom_postgui.hal
# Połącz pin z przycisku z sygnałem włączenia wrzeciona
# UWAGA: To jest tylko prosty przykład!
# Po kliknięciu przycisku, pin HAL zostanie przełączony.
# net moj-wlasny-przycisk-signal <= qtdragon_hd.wlasny-przycisk_is-on

166
custom_qtdragon.md Normal file
View File

@@ -0,0 +1,166 @@
# Modyfikacja Interfejsu qtdragon_hd w LinuxCNC
Data: 2025-12-12
## 1. Cel
Głównym celem jest dodanie nowej, niestandardowej zakładki z własnymi przyciskami do interfejsu `qtdragon_hd` w LinuxCNC. Kluczowe założenia to:
- Wykorzystanie wbudowanego, ukrytego przycisku `btn_user`, przeznaczonego do tego celu.
- Minimalna ingerencja w oryginalne pliki systemowe LinuxCNC.
- Stworzenie rozwiązania modułowego, gdzie logika i wygląd nowej zakładki są oddzielone od głównego interfejsu.
## 2. Podjęte Kroki i Stworzone Pliki
1. **Analiza i Strategia:** Zidentyfikowaliśmy, że plik `qtdragon_hd.ui` zawiera przycisk `btn_user` i `QStackedWidget` o nazwie `stackedWidget_mainTab`. Zdecydowaliśmy się nie modyfikować tego pliku, a zamiast tego dynamicznie załadować naszą zakładkę za pomocą niestandardowego handlera w Pythonie.
2. **Stworzenie plików w `~/linuxcnc/configs/mayo-mill_hd/`**:
- `qtvcp/screens/qtdragon_hd/qtdragon_hd.ui`: Lokalna kopia domyślnego pliku UI, stworzona w celu uniknięcia modyfikacji pliku systemowego.
- `qtvcp/screens/qtdragon_hd/my_user_tab.ui`: Plik UI zawierający *tylko zawartość* naszej nowej zakładki (jeden przycisk testowy).
- `qtvcp/screens/qtdragon_hd/handler.py`: Plik Pythona z klasą `MyHandler`, która zawiera logikę ładowania zakładki i obsługi przycisków.
- `custom_postgui.hal`: Plik do podłączenia pinów HAL z interfejsu do logiki maszyny.
3. **Konfiguracja:** Zmodyfikowaliśmy plik `mayo-mill.ini`, dodając w sekcji `[DISPLAY]` wpis: `HANDLER = handler.MyHandler`.
## 3. Napotkane Problemy i Diagnoza
1. **Błąd pinu HAL:** Wystąpił błąd `Pin ... does not exist`, ponieważ `custom_postgui.hal` był przetwarzany, zanim handler w Pythonie zdążył utworzyć pin. Problem nasilał się przez użycie kropki w nazwie pinu, która jest znakiem specjalnym w HAL.
- **Status:** Problem tymczasowo ominięto przez zakomentowanie linii w `custom_postgui.hal`.
2. **Główny Problem: Handler nie był ładowany:** Mimo poprawnego wpisu w `.ini`, logi startowe LinuxCNC pokazały, że system ignorował nasz plik `handler.py` i ładował domyślny handler systemowy (`/usr/share/qtvcp/screens/qtdragon_hd/qtdragon_hd_handler.py`).
- **Diagnoza:** Nasz plik i klasa `MyHandler` nie były powiązane z domyślnym handlerem. Przez to QTVCP nie traktował go jako rozszerzenia, a jako zupełnie osobny byt, który w tym wypadku został zignorowany na rzecz domyślnej implementacji. Próba zmiany nazwy pliku na `qtdragon_hd_handler.py` spowodowała konflikt i nadpisanie domyślnej logiki, co jest błędne.
## 4. Poprawne Rozwiązanie (do wdrożenia)
Aby poprawnie rozszerzyć funkcjonalność `qtdragon_hd`, nasz niestandardowy handler musi **dziedziczyć** po klasie handlera domyślnego. W ten sposób zachowujemy całą oryginalną funkcjonalność i tylko dodajemy naszą własną.
**Następne kroki do wykonania:**
1. Zastąpić zawartość pliku `handler.py` poniższym, **poprawionym kodem**, który implementuje dziedziczenie.
2. Uruchomić LinuxCNC i zweryfikować, czy zakładka "USER" się pojawiła.
3. Opcjonalnie: odkomentować linię w `custom_postgui.hal`, aby przetestować działanie pinu HAL.
---
### Docelowy Kod `handler.py` (z dziedziczeniem)
```python
# -*- coding: utf-8 -*-
# Plik: handler.py
import os
# Krok 1: Importujemy domyślny handler qtdragon_hd
from qtvcp.screens.qtdragon_hd import qtdragon_hd_handler
from qtvcp.core import Info
from qtvcp.widgets.widget_base import WidgetBase
from PyQt5.QtWidgets import QPushButton
print(">>> WŁASNY HANDLER: Plik handler.py został załadowany.")
PATH = Info().get_config_path()
# Krok 2: Nasza klasa dziedziczy po 'HandlerClass' z domyślnego handlera
class MyHandler(qtdragon_hd_handler.HandlerClass):
"""
Niestandardowy handler, który ROZSZERZA domyślny handler qtdragon_hd.
"""
def __init__(self, *args, **kwargs):
# Krok 3: Wywołujemy __init__ klasy nadrzędnej
super(MyHandler, self).__init__(*args, **kwargs)
print(">>> WŁASNY HANDLER: __init__ wykonany.")
def initialized(self):
# Krok 4: Wywołujemy initialized klasy nadrzędnej, aby cała domyślna logika się wykonała
super(MyHandler, self).initialized()
print(">>> WŁASNY HANDLER: Metoda 'initialized' została wywołana (po domyślnym handlerze).")
# --- Od tego momentu zaczyna się nasza własna logika ---
# Tworzymy nasz własny pin
self.my_custom_button_pin = self.hal.newpin("wlasny-przycisk_is-on", "HAL_BIT", "out")
print(f">>> WŁASNY HANDLER: Pin HAL '{self.my_custom_button_pin.name}' został stworzony.")
user_tab_ui_file = os.path.join(PATH, 'qtvcp', 'screens', 'qtdragon_hd', 'my_user_tab.ui')
print(f">>> WŁASNY HANDLER: Sprawdzam ścieżkę: {user_tab_ui_file}")
if not os.path.exists(user_tab_ui_file):
print(">>> WŁASNY HANDLER: BŁĄD! Nie znaleziono pliku my_user_tab.ui.")
self.widgets.btn_user.setVisible(False)
return
print(">>> WŁASNY HANDLER: Plik my_user_tab.ui znaleziony. Ładuję...")
self.user_tab_widget = WidgetBase()
self.user_tab_widget.load_ui(user_tab_ui_file)
main_stack = self.widgets.stackedWidget_mainTab
user_button = self.widgets.btn_user
target_index = user_button.property('index')
main_stack.insertWidget(target_index, self.user_tab_widget)
user_button.setVisible(True)
print(f">>> WŁASNY HANDLER: Zakładka wstawiona na indeks {target_index}, przycisk USER widoczny.")
my_button = self.user_tab_widget.findChild(QPushButton, 'moj_wlasny_przycisk_1')
if my_button:
my_button.clicked.connect(self.on_my_custom_button_clicked)
print(">>> WŁASNY HANDLER: Połączono sygnał z 'moj_wlasny_przycisk_1'.")
def on_my_custom_button_clicked(self):
current_state = self.my_custom_button_pin.get()
self.my_custom_button_pin.set(not current_state)
print(f">>> WŁASNY HANDLER: Klik! Nowy stan pinu: {not current_state}")
```
### Plik `my_user_tab.ui`
```xml
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UserTabWidget</class>
<widget class="QWidget" name="UserTabWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="moj_wlasny_przycisk_1">
<property name="minimumSize">
<size>
<width>150</width>
<height>50</height>
</size>
</property>
<property name="text">
<string>Mój Własny Przycisk Testowy</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
```

View File

@@ -26,6 +26,7 @@ INTRO_GRAPHIC = linuxcnc.gif
INTRO_TIME = 5
PROGRAM_PREFIX = /home/cnc/linuxcnc/nc_files
INCREMENTS = 5mm 1mm .5mm .1mm .05mm .01mm .005mm
HANDLER = handler.MyHandler
[KINS]
JOINTS = 3

141
qtdragon_hd.pre Normal file
View File

@@ -0,0 +1,141 @@
[DIALOG_GEOMETRY]
AboutDialog-geometry = half
LncMessage-geometry = 910 525 280 118
ToolChangeDialog-geometry = 910 525 340 237
VersaHelpDialog-geometry = default
CalculatorDialog-geometry = 910 525 472 376
[DIALOG_OPTIONS]
EntryDialog_play_sound = True
EntryDialog_sound_type = READY
toolDialog_play_sound = True
toolDialog_speak = True
toolDialog_sound_type = READY
fileDialog_play_sound = True
fileDialog_sound_type = READY
CalculatorDialog_play_sound = True
CalculatorDialog_sound_type = READY
MachineLogDialog_play_sound = True
MachineLogDialog_sound_type = READY
RunFromLineDialog_play_sound = True
RunFromLineDialog_sound_type = READY
[BOOK_KEEPING]
last_loaded_directory =
last_loaded_file = None
style_QSS_Path = DEFAULT
[ORIGINOFFSET_SYSTEM_NAMES]
__dialogOffsetViewWidget-G54 = User System 1
__dialogOffsetViewWidget-G55 = User System 2
__dialogOffsetViewWidget-G56 = User System 3
__dialogOffsetViewWidget-G57 = User System 4
__dialogOffsetViewWidget-G58 = User System 5
__dialogOffsetViewWidget-G59 = User System 6
__dialogOffsetViewWidget-G59.1 = User System 7
__dialogOffsetViewWidget-G59.2 = User System 8
__dialogOffsetViewWidget-G59.3 = User System 9
offset_table-G54 = User System 1
offset_table-G55 = User System 2
offset_table-G56 = User System 3
offset_table-G57 = User System 4
offset_table-G58 = User System 5
offset_table-G59 = User System 6
offset_table-G59.1 = User System 7
offset_table-G59.2 = User System 8
offset_table-G59.3 = User System 9
[SCREEN_OPTIONS]
catch_errors = True
desktop_notify = True
notify_max_msgs = 10
shutdown_check = True
sound_player_on = False
MainWindow-geometry = 0 0 1920 1080
[MCH_MSG_OPTIONS]
mchnMsg_play_sound = True
mchnMsg_speak_errors = False
mchnMsg_speak_text = True
mchnMsg_sound_type = ATTENTION
[USR_MSG_OPTIONS]
usermsg_play_sound = True
userMsg_sound_type = ATTENTION
userMsg_use_focusOverlay = True
[SHUTDOWN_OPTIONS]
shutdown_play_sound = True
shutdown_alert_sound_type = READY
shutdown_exit_sound_type = LOGOUT
shutdown_msg_title = Do you want to Shutdown now?
shutdown_msg_focus_text =
shutdown_msg_detail =
[NOTIFY_OPTIONS]
notify_start_greeting = False
notify_start_title = Welcome
notify_start_detail = This option can be changed in the preference file
notify_start_timeout = 5
[FILEMANAGER_JUMPLIST]
[SCREEN_CONTROL_LAST_SETTING]
gcodegraphics-user-view = p
gcodegraphics-user-zoom = 10.0
gcodegraphics-user-panx = 0.0
gcodegraphics-user-pany = 0.0
gcodegraphics-user-lat = 0.0
gcodegraphics-user-lon = 0.0
[CUSTOM_FORM_ENTRIES]
Tool to load = 0
Laser X = 100.0
Laser Y = -20.0
Sensor X = 10.0
Sensor Y = 10.0
Camera X = 10.0
Camera Y = 10.0
Work Height = 20.0
Touch Height = 40.0
Sensor Height = 40.0
Search Velocity = 40.0
Probe Velocity = 10.0
Max Probe = 10.0
Retract Distance = 10.0
Z Safe Travel = 10.0
Eoffset count = 0
External offsets = False
Reload program = False
Reload tool = False
Use keyboard = False
Use tool sensor = False
Use tool touchplate = False
Run from line = False
Use virtual keyboard = False
Use camera = False
Use alpha display mode = False
Inhibit display mouse selection = True
Camview xscale = 100
Camview yscale = 100
Camview cam number = 0
[VERSA_PROBE_OPTIONS]
ps_searchvel = 300.0
ps_probevel = 10.0
ps_z_clearance = 3.0
ps_probe_max = 1.0
ps_probe_max_z_travel = 1.0
ps_probe_latch = 0.5
ps_probe_diam = 2.0
ps_xy_clearance = 5.0
ps_side_edge_length = 5.0
ps_probe_height = 20.0
ps_block_height = 20.0
use_tool_measurement = True
ps_offs_x = 0.0
ps_offs_y = 0.0
ps_offs_z = 0.0
ps_offs_angle = 0.0
ps_probe_rapid_vel = 60.0

View File

@@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
# handler.py
import os
from qtvcp.core import Handler, Info
from qtvcp.widgets.widget_base import WidgetBase
from PyQt5.QtWidgets import QPushButton
print("Plik handler.py został załadowany przez Pythona.")
# Pobierz sciezke do naszej konfiguracji
PATH = Info().get_config_path()
class MyHandler(Handler):
"""
Główna klasa handlera, która dynamicznie ładuje zakładkę użytkownika.
WERSJA DEBUG.
"""
def __init__(self, *args, **kwargs):
"""
Metoda __init__ jest wywoływana przy starcie.
"""
super(MyHandler, self).__init__(*args, **kwargs)
print(">>> HANDLER: __init__ został wykonany. Obiekt MyHandler stworzony.")
# Tworzymy pin HAL dla naszego własnego przycisku
self.my_custom_button_pin = self.hal.newpin("wlasny-przycisk_is-on", "HAL_BIT", "out")
print(f">>> HANDLER: Pin HAL '{self.my_custom_button_pin.name}' został stworzony.")
def initialized(self):
"""
Ta metoda jest wywoływana, gdy interfejs jest już załadowany.
Tutaj wczytujemy nasz plik UI i wstawiamy go do stackedWidget.
"""
print(">>> HANDLER: Metoda 'initialized' została wywołana.")
# Ścieżka do naszego pliku UI z zawartością zakładki
user_tab_ui_file = os.path.join(PATH, 'qtvcp', 'screens', 'qtdragon_hd', 'my_user_tab.ui')
print(f">>> HANDLER: Sprawdzam ścieżkę do pliku UI: {user_tab_ui_file}")
if not os.path.exists(user_tab_ui_file):
print(">>> HANDLER: BŁĄD KRYTYCZNY! Nie znaleziono pliku my_user_tab.ui. Przycisk 'USER' nie zostanie aktywowany.")
self.widgets.btn_user.setVisible(False)
return
print(">>> HANDLER: Plik my_user_tab.ui ZOSTAŁ ZNALEZIONY. Próbuję go załadować.")
# Załaduj zawartość z pliku .ui do nowego widżetu
self.user_tab_widget = WidgetBase()
self.user_tab_widget.load_ui(user_tab_ui_file)
print(">>> HANDLER: Plik UI załadowany pomyślnie do widżetu.")
# Główne QStackedWidget z oryginalnego UI
main_stack = self.widgets.stackedWidget_mainTab
user_button = self.widgets.btn_user
target_index = user_button.property('index')
# Wstawiamy nasz nowy widżet
main_stack.insertWidget(target_index, self.user_tab_widget)
print(f">>> HANDLER: Widżet wstawiony do stackedWidget_mainTab na indeksie {target_index}.")
# Upewnij się, że przycisk USER jest widoczny
user_button.setVisible(True)
print(">>> HANDLER: Próba ustawienia przycisku 'btn_user' jako WIDOCZNY.")
# Znajdź nasz własny przycisk w załadowanym widżecie i połącz jego sygnał
my_button = self.user_tab_widget.findChild(QPushButton, 'moj_wlasny_przycisk_1')
if my_button:
my_button.clicked.connect(self.on_my_custom_button_clicked)
print(">>> HANDLER: Znaleziono 'moj_wlasny_przycisk_1' i połączono jego sygnał 'clicked'.")
else:
print(">>> HANDLER: OSTRZEŻENIE: Nie znaleziono przycisku 'moj_wlasny_przycisk_1' w my_user_tab.ui")
def on_my_custom_button_clicked(self):
current_state = self.my_custom_button_pin.get()
self.my_custom_button_pin.set(not current_state)
print(f">>> HANDLER: Kliknięto własny przycisk! Nowy stan pinu HAL: {not current_state}")

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UserTabWidget</class>
<widget class="QWidget" name="UserTabWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="moj_wlasny_przycisk_1">
<property name="minimumSize">
<size>
<width>150</width>
<height>50</height>
</size>
</property>
<property name="text">
<string>Mój Własny Przycisk Testowy</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
T0 P0 ;Probe
T1 P1 D+0.850000 ;0.85 Flat end mill
T2 P2 D+3.175000 Z-0.012833 ;3.175 Flat end mill
T3 P3 D+3.175000 ;3.175 Engrave mill 30* 0.2
T4 P4 D+6.000000 Z+15.800167 ;6mm Flat end mill
T5 P0 D+1.000000 Z-0.001500 ;1mm Flat end mill
T6 P0 D+0.800000 ;drill 0.7
T0 P0 X0 Y0 Z0 A0 B0 C0 U0 V0 W0 D0 I0 J0 Q0 ;Probe
T1 P1 X0 Y0 Z0 A0 B0 C0 U0 V0 W0 D0.85000 I0 J0 Q0 ;0.85 Flat end mill
T2 P2 X0 Y0 Z-0.01283 A0 B0 C0 U0 V0 W0 D3.17500 I0 J0 Q0 ;3.175 Flat end mill
T3 P3 X0 Y0 Z0 A0 B0 C0 U0 V0 W0 D3.17500 I0 J0 Q0 ;3.175 Engrave mill 30* 0.2
T4 P4 X0 Y0 Z15.80017 A0 B0 C0 U0 V0 W0 D6.00000 I0 J0 Q0 ;6mm Flat end mill
T5 P0 X0 Y0 Z0 A0 B0 C0 U0 V0 W0 D1.00000 I0 J0 Q0 ;1mm Flat end mill
T6 P0 X0 Y0 Z0 A0 B0 C0 U0 V0 W0 D0.80000 I0 J0 Q0 ;drill 0.7