Navigation.remove_all() löscht Toolbar/Menü nicht wirklich – Plugin-Reloader meldet "duplicated widget(s) not cleaned up" #72

Closed
opened 2026-09-21 08:18:25 +00:00 by Daniel · 0 comments
Member

Ziel

Nach Plugin Reloader-Neuladen von sn_basis erscheint keine Warnung mehr "removing duplicated widget(s)
not cleaned up by the plugin during unload: LnoSachsenToolbar" – Unload entfernt Toolbar und Menü
tatsächlich aus dem Qt-Objektbaum, nicht nur aus der sichtbaren Toolbar-/Menüleiste.

Betroffen

Plugin: sn_basis
Module/Dateien:

  • ui/navigation.py (Navigation.remove_all)
    Berührt Schnittstellen (docs/architektur/schnittstellen.md)? nein

Fachlicher Hintergrund

Navigation.remove_all() (Zeilen 116-126) ruft beim Unload nur remove_toolbar(self.toolbar) bzw.
remove_menu(self.menu) auf. Diese Wrapper (functions/qgisui_wrapper.py, remove_toolbar/remove_menu)
rufen wiederum nur iface.removeToolBar() bzw. main_window.menuBar().removeAction() – das entfernt das
Widget aus der sichtbaren Leiste, zerstört aber nicht das Qt-Objekt. Es bleibt als Kind von main_window
bestehen und taucht bei main_window.findChildren(QToolBar) weiter auf.

Navigation.init_ui() (Zeilen 40-46) hat dafür bereits einen defensiven Workaround: beim nächsten Laden
sucht es aktiv nach übrig gebliebenen Toolbars mit objectName() == "LnoSachsenToolbar" und ruft dort
deleteLater() auf. Das kaschiert das Problem nur beim nächsten Laden; der QGIS Plugin Reloader entdeckt
die Leiche dazwischen (nach unload(), vor dem erneuten initGui()) und räumt sie selbst weg – daher die
Warnmeldung.

Reiner Mock-Modus-Test kann das nicht fangen: tests/test_navigation.py::test_entfernt_menu_toolbar_und_setzt_zustand_zurueck
patcht remove_toolbar/remove_menu komplett weg und prüft nur, dass sie aufgerufen wurden – ein echter
Qt-Objektbaum mit findChildren() existiert im Mock-Modus nicht.

Abnahmekriterien

  • Navigation.remove_all() ruft self.toolbar.deleteLater() und self.menu.deleteLater() auf, bevor
    die Referenzen auf None gesetzt werden (analog zum bestehenden Workaround in init_ui())
  • Mock-Test: remove_all() ruft auf einem Toolbar-/Menü-Double deleteLater() auf
  • run_tests.py sn_basis --baseline ohne NEU ROT
  • QGIS-Test: sn_basis mit Plugin Reloader mehrfach neu laden, keine "duplicated widget(s)"-Warnung mehr
    in der QGIS-Log-Konsole

Nicht Teil dieses Issues

  • Der defensive Workaround in init_ui() (Zeilen 40-46) kann nach dem Fix entfernt werden, ist aber nicht
    zwingend Teil dieses Issues – falls entfernt, im PR begründen.
## Ziel Nach `Plugin Reloader`-Neuladen von sn_basis erscheint keine Warnung mehr "removing duplicated widget(s) not cleaned up by the plugin during unload: LnoSachsenToolbar" – Unload entfernt Toolbar und Menü tatsächlich aus dem Qt-Objektbaum, nicht nur aus der sichtbaren Toolbar-/Menüleiste. ## Betroffen Plugin: sn_basis Module/Dateien: - `ui/navigation.py` (`Navigation.remove_all`) Berührt Schnittstellen (`docs/architektur/schnittstellen.md`)? nein ## Fachlicher Hintergrund `Navigation.remove_all()` (Zeilen 116-126) ruft beim Unload nur `remove_toolbar(self.toolbar)` bzw. `remove_menu(self.menu)` auf. Diese Wrapper (`functions/qgisui_wrapper.py`, `remove_toolbar`/`remove_menu`) rufen wiederum nur `iface.removeToolBar()` bzw. `main_window.menuBar().removeAction()` – das entfernt das Widget aus der sichtbaren Leiste, zerstört aber nicht das Qt-Objekt. Es bleibt als Kind von `main_window` bestehen und taucht bei `main_window.findChildren(QToolBar)` weiter auf. `Navigation.init_ui()` (Zeilen 40-46) hat dafür bereits einen defensiven Workaround: beim nächsten Laden sucht es aktiv nach übrig gebliebenen Toolbars mit `objectName() == "LnoSachsenToolbar"` und ruft dort `deleteLater()` auf. Das kaschiert das Problem nur beim nächsten Laden; der QGIS Plugin Reloader entdeckt die Leiche dazwischen (nach `unload()`, vor dem erneuten `initGui()`) und räumt sie selbst weg – daher die Warnmeldung. Reiner Mock-Modus-Test kann das nicht fangen: `tests/test_navigation.py::test_entfernt_menu_toolbar_und_setzt_zustand_zurueck` patcht `remove_toolbar`/`remove_menu` komplett weg und prüft nur, dass sie aufgerufen wurden – ein echter Qt-Objektbaum mit `findChildren()` existiert im Mock-Modus nicht. ## Abnahmekriterien - [ ] `Navigation.remove_all()` ruft `self.toolbar.deleteLater()` und `self.menu.deleteLater()` auf, bevor die Referenzen auf `None` gesetzt werden (analog zum bestehenden Workaround in `init_ui()`) - [ ] Mock-Test: `remove_all()` ruft auf einem Toolbar-/Menü-Double `deleteLater()` auf - [ ] `run_tests.py sn_basis --baseline` ohne NEU ROT - [ ] QGIS-Test: sn_basis mit Plugin Reloader mehrfach neu laden, keine "duplicated widget(s)"-Warnung mehr in der QGIS-Log-Konsole ## Nicht Teil dieses Issues - Der defensive Workaround in `init_ui()` (Zeilen 40-46) kann nach dem Fix entfernt werden, ist aber nicht zwingend Teil dieses Issues – falls entfernt, im PR begründen.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: AG_QGIS/Plugin_SN_Basis#72