LCOV - code coverage report
Current view: top level - src/pairinteraction_gui - app.py (source / functions) Hit Total Coverage
Test: coverage.info Lines: 24 37 64.9 %
Date: 2025-06-06 09:09:03 Functions: 2 10 20.0 %

          Line data    Source code
       1             : # SPDX-FileCopyrightText: 2025 Pairinteraction Developers
       2             : # SPDX-License-Identifier: LGPL-3.0-or-later
       3             : 
       4           1 : import logging
       5           1 : import os
       6           1 : import signal
       7           1 : from types import FrameType
       8           1 : from typing import Optional
       9             : 
      10           1 : from PySide6.QtCore import QObject, QSocketNotifier, QTimer, Signal
      11           1 : from PySide6.QtWidgets import QApplication
      12             : 
      13           1 : from pairinteraction_gui.worker import MultiProcessWorker, MultiThreadWorker
      14             : 
      15           1 : logger = logging.getLogger(__name__)
      16             : 
      17             : 
      18           1 : class MainSignals(QObject):
      19             :     """Signals for the application.
      20             : 
      21             :     We store an instance of this signal class in the Application instance, see app.py.
      22             :     So to access these signals (from anywhere in the application), you can use
      23             :     `Application.instance().signals`.
      24             :     """
      25             : 
      26           1 :     ask_download_database = Signal(str)
      27             : 
      28             : 
      29           1 : class Application(QApplication):
      30             :     """Add some global signals to the QApplication."""
      31             : 
      32           1 :     signals = MainSignals()
      33             : 
      34           1 :     @classmethod
      35           1 :     def instance(cls) -> "Application":
      36             :         """Return the current instance of the application."""
      37           1 :         return super().instance()  # type: ignore [return-value]
      38             : 
      39           1 :     def allow_ctrl_c(self) -> None:
      40             :         # Create a pipe to communicate between the signal handler and the Qt event loop
      41           0 :         pipe_r, pipe_w = os.pipe()
      42             : 
      43           0 :         def signal_handler(signal: int, frame: Optional[FrameType]) -> None:
      44           0 :             os.write(pipe_w, b"x")  # Write a single byte to the pipe
      45             : 
      46           0 :         signal.signal(signal.SIGINT, signal_handler)
      47             : 
      48           0 :         def handle_signal() -> None:
      49           0 :             os.read(pipe_r, 1)  # Read the byte from the pipe to clear it
      50           0 :             logger.info("Ctrl+C detected in terminal. Shutting down gracefully...")
      51           0 :             self.quit()
      52             : 
      53           0 :         sn = QSocketNotifier(pipe_r, QSocketNotifier.Type.Read, parent=self)
      54           0 :         sn.activated.connect(handle_signal)
      55             : 
      56             :         # Create a timer to ensure the event loop processes events regularly
      57             :         # This makes Ctrl+C work even when the application is idle
      58           0 :         timer = QTimer(self)
      59           0 :         timer.timeout.connect(lambda: None)  # Do nothing, just wake up the event loop
      60           0 :         timer.start(200)
      61             : 
      62           1 :     @staticmethod
      63           1 :     def quit() -> None:
      64             :         """Quit the application."""
      65           1 :         logger.debug("Calling Application.quit().")
      66           1 :         MultiProcessWorker.terminate_all(create_new_pool=False)
      67           1 :         MultiThreadWorker.terminate_all()
      68           1 :         QApplication.quit()
      69           1 :         logger.debug("Application.quit() done.")

Generated by: LCOV version 1.16