#!D:/IDE/anaconda3/envs/Microscope_Scan python
# -*- coding: UTF-8 -*-
"""
@FileName：ActionController.py
@Description：
@Author：XSH
@Time：2025/11/17 18:53
@Department：研发部
@Copyright：©2025 乐辰生物
"""
import sys
import os
from PyQt5                      import Qt
from AppSettings.Settings       import *
from AppInterfaces.utils        import *
from AppCore.Levels             import *
from AppUtils.UiUtils           import UiUtils
from AppCore.DBModels           import *
from AppUtils.utils             import *
from AppUtils.utils                     import *
from AppInterfaces.UiInterface          import UiInterface
from AppBackEnd.AppBusinessInterface    import AppBusinessInterface
from AppHeadEnd.ControllerViews.ManipulatorController   import ManipulatorController   #
from AppHeadEnd.ControllerViews.PositionController      import PositionController      #
from AppHeadEnd.ControllerViews.PositionOperation       import PositionOperation       #
from AppHeadEnd.ControllerViews.TrayOperation           import TrayOperation           #
from AppHeadEnd.ControllerViews.ControllerOperation     import ControllerOperation     #
from AppHeadEnd.ControllerViews.CameraController        import CameraController        #
from AppHeadEnd.ControllerViews.MicroscopeController    import MicroscopeController    #
from AppHeadEnd.ControllerFrames.ControlFrameInterface  import ControlFrameInterface   #
from AppHeadEnd.ControllerViews.DBOperation import DBOperation
from AppUtils.ImageUtils import ImageUtils
class ActionController(Qt.QWidget, ControlFrameInterface):
    Controller          : ManipulatorController         #
    Chamber             : TrayOperation                 #
    Position            : PositionOperation             #
    Operation           : ControllerOperation           #
    CameraView          : DBOperation                   #
    CameraTimer         : Qt.QTimer                     #
    def __init__(self, business: AppBusinessInterface, parent: Qt.QObject = None):
        super(ActionController, self).__init__(parent=parent)
        self.Business = business if isinstance(business, AppBusinessInterface) else None
        self.Initialization('ActionController', self, parent)
        self.initWidgetStyle()



    def initValue(self):
        super(ActionController, self).initValue()
        self.initController  ()
        self.initChamber     ()
        self.initPosition    ()
        self.initOperation   ()
        self.initCameraView  ()
        self.initCameraTimer ()
        self.Controller.DebugButton.setText('清除告警')


    def initProperty(self):
        super(ActionController, self).initProperty()

    def initLayouts(self):
        super(ActionController, self).initLayouts()
        if self.hasWindowLayouts:
            return

        main_layout: Qt.QHBoxLayout = Qt.QHBoxLayout()
        main_layout.setSpacing(5)  # 设置布局间距
        main_layout.setContentsMargins(5, 5, 5, 5)

        row1: Qt.QVBoxLayout = Qt.QVBoxLayout()
        row1.setSpacing(1)  # 设置布局间距
        row1.setContentsMargins(1, 1, 1, 1)

        row2: Qt.QVBoxLayout = Qt.QVBoxLayout()
        row2.setSpacing(1)  # 设置布局间距
        row2.setContentsMargins(1, 1, 1, 1)

        box_layout: Qt.QVBoxLayout = Qt.QVBoxLayout()
        box_layout.setSpacing(2)  # 设置布局间距
        box_layout.setContentsMargins(5, 20, 5, 5)

        box_layout.addWidget(self.Chamber             )
        box_layout.addWidget(self.Position            )
        box_layout.addWidget(self.Operation           )
        group_box: Qt.QGroupBox = Qt.QGroupBox()
        group_box.setLayout(box_layout)


        row1.setAlignment(Qt.Qt.AlignTop | Qt.Qt.AlignHCenter)
        row1.addWidget(self.Controller          )
        row1.addWidget(group_box)
        group_box.setStyleSheet(UiUtils.getGroupBoxStyle())
        row2.addWidget(self.CameraView)




        # main_layout.addLayout(row1, 0, 0, -1, 2 , Qt.Qt.AlignTop | Qt.Qt.AlignHCenter)
        # main_layout.addLayout(row2, 0, 3, -1, -1, Qt.Qt.AlignTop | Qt.Qt.AlignHCenter)
        main_layout.addLayout(row1)
        main_layout.addLayout(row2)
        # 设置主布局
        self.setLayout(main_layout)


    def initController (self):
        if not self.hasController :
            self.Controller  = ManipulatorController   (self)

    def initPosition   (self):
        if not self.hasPosition   :
            self.Position    = PositionOperation      (self)

    def initOperation  (self):
        if not self.hasOperation  :
            self.Operation   = ControllerOperation     (self)

    def initCameraView (self):
        if not self.hasCameraView :
            self.CameraView  = DBOperation            (self)

    def initCameraTimer(self):
        if not self.hasCameraTimer:
            self.CameraTimer = Qt.QTimer(self)
            self.CameraTimer.timeout.connect(slot=self.SlotCameraTimer, type=Qt.Qt.ConnectionType(Qt.Qt.AutoConnection | Qt.Qt.UniqueConnection))
    def initChamber(self):
        if not self.hasChamber:
            self.Chamber = TrayOperation(self)

    @property
    def hasController (self) -> bool:
        return hasattr(self, 'Controller' ) and isinstance(self.Controller, ManipulatorController)

    @property
    def hasChamber             (self) -> bool:
        return hasattr(self, 'Chamber'   ) and isinstance(self.Chamber             , TrayOperation    )

    @property
    def hasPosition            (self) -> bool:
        return hasattr(self, 'Position'  ) and isinstance(self.Position            , PositionOperation)


    @property
    def hasOperation   (self) -> bool:
        return hasattr(self, 'Operation'   ) and isinstance(self.Operation  , ControllerOperation  )

    @property
    def hasCameraView  (self) -> bool:
        return hasattr(self, 'CameraView'  ) and isinstance(self.CameraView , DBOperation     )


    def initConnect(self):
        super(ActionController, self).initConnect()
        TYPE: Qt.Qt.ConnectionType = Qt.Qt.ConnectionType(Qt.Qt.AutoConnection | Qt.Qt.UniqueConnection)
        # AppSlot.CameraUiSignal.connect(slot=self.CameraView.CameraView.SlotCameraUiSignal, type=TYPE)
        self.Controller.YPlusButton           .clicked.connect(slot=self.SlotYPlusButton           , type=TYPE)
        self.Controller.YMinusButton          .clicked.connect(slot=self.SlotYMinusButton          , type=TYPE)
        self.Controller.XPlusButton           .clicked.connect(slot=self.SlotXPlusButton           , type=TYPE)
        self.Controller.XMinusButton          .clicked.connect(slot=self.SlotXMinusButton          , type=TYPE)
        self.Controller.ZPlusButton           .clicked.connect(slot=self.SlotZPlusButton           , type=TYPE)
        self.Controller.ZMinusButton          .clicked.connect(slot=self.SlotZMinusButton          , type=TYPE)
        self.Controller.MicPlusButton         .clicked.connect(slot=self.SlotMicPlusButton         , type=TYPE)
        self.Controller.MicMinusButton        .clicked.connect(slot=self.SlotMicMinusButton        , type=TYPE)
        self.Controller.HPlusButton           .clicked.connect(slot=self.SlotHPlusButton           , type=TYPE)
        self.Controller.HMinusButton          .clicked.connect(slot=self.SlotHMinusButton          , type=TYPE)
        self.Controller.ScanCodeButton        .clicked.connect(slot=self.SlotScanCodeButton        , type=TYPE)
        self.Controller.CodeCompleteButton    .clicked.connect(slot=self.SlotCodeCompleteButton    , type=TYPE)
        self.Controller.CameraSwitch          .clicked.connect(slot=self.SlotCameraSwitch          , type=TYPE)
        self.Controller.CameraButton          .clicked.connect(slot=self.SlotCameraButton          , type=TYPE)
        self.Controller.InitXYButton          .clicked.connect(slot=self.SlotInitXYButton          , type=TYPE)
        self.Controller.InitZButton           .clicked.connect(slot=self.SlotInitZButton           , type=TYPE)
        self.Controller.InitHButton           .clicked.connect(slot=self.SlotInitHButton           , type=TYPE)
        self.Controller.InitMicButton         .clicked.connect(slot=self.SlotInitMicButton         , type=TYPE)
        self.Controller.InitCodeButton        .clicked.connect(slot=self.SlotInitCodeButton        , type=TYPE)
        self.Controller.InitCameraButton      .clicked.connect(slot=self.SlotInitCameraButton      , type=TYPE)
        self.Controller.DebugButton           .clicked.connect(slot=self.SlotDebugButton           , type=TYPE)
        self.Controller.ObjectiveLabel        .clicked.connect(slot=self.SlotObjectiveEdit         , type=TYPE)
        self.Controller.OilButton             .clicked.connect(slot=self.SlotOilButton             , type=TYPE)

        self.Operation.InitButton              .clicked.connect(slot=self.SlotInitButton              , type=TYPE)
        self.Operation.SafeButton              .clicked.connect(slot=self.SlotSafeButton              , type=TYPE)
        self.Operation.LowScanningSlide        .clicked.connect(slot=self.SlotLowScanningSlide        , type=TYPE)
        self.Operation.HigScanningSlide        .clicked.connect(slot=self.SlotHigScanningSlide        , type=TYPE)
        self.Operation.ScanningChamber         .clicked.connect(slot=self.SlotScanningChamber         , type=TYPE)
        self.Operation.ScanningTray            .clicked.connect(slot=self.SlotScanningTray            , type=TYPE)
        self.Operation.CheckChamberButton      .clicked.connect(slot=self.SlotCheckChamberButton      , type=TYPE)
        self.Operation.CheckTrayButton         .clicked.connect(slot=self.SlotCheckTrayButton         , type=TYPE)
        self.Operation.PickChamberTrayButton   .clicked.connect(slot=self.SlotPickChamberTrayButton   , type=TYPE)
        self.Operation.DropChamberTrayButton   .clicked.connect(slot=self.SlotDropChamberTrayButton   , type=TYPE)
        self.Operation.EmptyHookReturnButton   .clicked.connect(slot=self.SlotEmptyHookReturnButton   , type=TYPE)
        self.Operation.QuitPLCLoopButton       .clicked.connect(slot=self.SlotQuitPLCLoopButton       , type=TYPE)


        self.Position.ReadButton                .clicked.connect(slot=self.SlotReadPositionButton, type=TYPE)
        self.Position.MoveButton                .clicked.connect(slot=self.SlotMovePositionButton, type=TYPE)

        self.Chamber.MoveLocationButton         .clicked.connect(slot=self.SlotMoveLocationButton, type=TYPE)
        self.CameraView.ActionMovesSignal.connect(slot=self.SlotActionMovesSignal, type=TYPE)

    def SlotMoveLocationButton(self):
        if not self.isAvailable():
            return
        from AppCore.DBModels import SlideModelInterface, SlideFocusingModel, ObjectiveModel
        chamber_number  : int = self.Chamber.getChamberNumber()
        objective       : int = self.Chamber.getObjective()
        tray_number     : int = self.Chamber.getTrayNumber()
        row_number      : int = self.Chamber.getRowNumber()
        col_number      : int = self.Chamber.getColNumber()
        Objective       : ObjectiveModel = ObjectiveModel.getConfig(objective)
        model: SlideModelInterface = SlideFocusingModel()
        model.ChamberGroupNumber = chamber_number
        model.ChamberRowNumber   = tray_number
        model.TrayNumber         = tray_number
        model.RowNumber          = row_number
        model.ColNumber          = col_number

        model.ObjectiveLevel     = objective

        SlideFocusingModel.setSlidePosition(tray_number, model)
        z: float = self.Position.getMPosition()
        if Float(z) == 0.0:
            model.Position_Z = Objective.Safe_Limit
        elif float(Objective.Lower_Limit) <= Float(z) <= float(Objective.Upper_Limit):
            model.Position_Z = z
        else:
            model.Position_Z = Objective.Safe_Limit
        model.Objective  = Objective
        self.wait_move_model(model)
        isWrong, x = self.manipulator.axis_x.get_position()
        self.Position.setXPosition(x)
        isWrong, y = self.manipulator.axis_y.get_position()
        self.Position.setYPosition(y)
        isWrong, z = self.microscope.get_position()
        self.Position.setMPosition(z)


    def SlotReadPositionButton(self):
        if not self.isAvailable():
            return
        x           : float
        y           : float
        z           : float
        objective   : int
        isWrong, x = self.manipulator.axis_x.get_position()
        self.Position.setXPosition(x)
        isWrong, y = self.manipulator.axis_y.get_position()
        self.Position.setYPosition(y)
        isWrong, z = self.microscope.get_position()
        self.Position.setMPosition(z)
        isWrong, objective = self.microscope.get_objective()
        self.Chamber.setObjective(objective)
        pass



    def SlotMovePositionButton(self):
        if not self.isAvailable():
            return
        from AppCore.DBModels import ObjectiveModel
        x           : float = self.Position.getXPosition    ()
        y           : float = self.Position.getYPosition    ()
        z           : float = self.Position.getMPosition    ()
        objective   : int   = self.Chamber.getObjective     ()
        isWrong, _objective = self.microscope.get_objective()
        self.microscope.init_z_range()
        Objective: ObjectiveModel = ObjectiveModel.getConfig(_objective)
        if _objective != objective:
            self.microscope.waitmove_z(Objective.Safe_Limit)
        if Float(z) <= float(Objective.Safe_Limit):
            self.microscope.waitmove_z(z)
        else:
            self.microscope.waitmove_z(Objective.Safe_Limit)
        self.manipulator.waitmove_xy(x, y)
        if _objective != objective:
            isWrong = self.microscope.set_objective(objective)
        else:
            isWrong = RECODE_SUCCEED
        if RECODE_SUCCEED == isWrong:
            Objective = ObjectiveModel.getConfig(objective)
            self.microscope.set_z_speed(Objective.Default_Speed)
            self.microscope.waitmove_z(z)

        isWrong, x = self.manipulator.axis_x.get_position()
        self.Position.setXPosition(x)
        isWrong, y = self.manipulator.axis_y.get_position()
        self.Position.setYPosition(y)
        isWrong, z = self.microscope.get_position()
        self.Position.setMPosition(z)
        pass


    def SlotActionMovesSignal(self, item):
        if not self.isAvailable():
            return
        if not  self.business.isManipulatorAvailable or not self.business.isMicroscopeAvailable:
            return
        from AppCore.DBModels import SlideModelInterface, ObjectiveModel, TrayModel, CellModel
        if not isinstance(item, SlideModelInterface):
            return
        if self.CameraView.CameraView.isCrosshair:
            tray_model: TrayModel = TrayModel.getTrayConfig(item.TrayNumber)
            CellModel.setCellPoint(tray_model, item)
        self.wait_move_model(item)

    def wait_move_model(self, item):
        from AppCore.DBModels import SlideModelInterface, ObjectiveModel, TrayModel
        if not isinstance(item, SlideModelInterface):
            return
        try:
            isWrong: int = RECODE_FAILURE
            objective: int
            isWrong, objective = self.microscope.get_objective()
            Objective: ObjectiveModel = ObjectiveModel.getConfig(item.ObjectiveLevel)
            self.microscope.init_z_range()
            self.microscope.set_z_speed(Objective.Default_Speed)
            if item.ObjectiveLevel != objective:
                self.microscope.waitmove_z(Objective.Safe_Limit)
                self.microscope.set_objective(item.ObjectiveLevel)
            else:
                self.microscope.waitmove_z(Objective.Safe_Limit)
            self.manipulator.waitmove_xy(item.Position_X, item.Position_Y)
            self.microscope.waitmove_z(item.Position_Z)
            self.camera.setModel(item.ObjectiveLevel)
        except Exception as e:
            AppUtils.print_Exception(e)


    def SlotInfoXPosition(self):
        if not self.isAvailable():
            return
        if not self.hasAxisX:
            return
        isWrong: int
        value: int
        isWrong, value = self.axis_x.get_position()
        self.Position.setXPosition(value)

    def SlotInfoYPosition(self):
        if not self.isAvailable():
            return
        if not self.hasAxisY:
            return
        isWrong: int
        value: int
        isWrong, value = self.axis_y.get_position()
        self.Position.setYPosition(value)


    def SlotInfoMPosition(self):
        if not self.isAvailable():
            return
        if not self.hasMicroscope:
            return
        isWrong: int
        value: int
        isWrong, value = self.microscope.get_position()
        self.Position.setMPosition(value)


    def SlotInfoObjective(self):
        if not self.isAvailable():
            return
        if not self.hasMicroscope:
            return
        isWrong: int
        value  : int
        isWrong, value = self.microscope.get_objective()
        self.Chamber.setObjective(value)


    def SlotInitButton            (self):
        if not self.isAvailable():
            return
        if not self.hasMotion:
            return
        if not self.axis_h.isAvailable:
            self.manipulator.initManager()
        if not self.axis_z.isAvailable:
            self.manipulator.initManager()

        isWrong: int = self.business.devices.waitForMotionHome()


    def SlotSafeButton(self):
        if not self.isAvailable():
            return
        if not self.hasMotion:
            return
        if not self.axis_h.isAvailable:
            self.manipulator.initManager()
        if not self.axis_z.isAvailable:
            self.manipulator.initManager()
        self.business.devices.waitmoveForSafe()



    def SlotPickChamberTrayButton (self):
        from AppCore.AppDBModels.ConfigModels.ChamberConfigModel import ChamberConfigModel
        if not self.isAvailable():
            return
        if not self.hasAxisH or not self.hasMicroscope:
            return
        if self.business.status.isExit:
            self.business.status.setRunning()
        layer: int = self.Chamber.getChamberNumber()
        self.business.ChamberToSlideTable(chamber_number=layer, isExit=False)
        self.business.status.setExit()

    def SlotDropChamberTrayButton (self):
        from AppCore.AppDBModels.ConfigModels.ChamberConfigModel import ChamberConfigModel
        if not self.isAvailable():
            return
        if not self.hasAxisH or not self.hasMicroscope:
            return
        if self.business.status.isExit:
            self.business.status.setRunning()
        layer: int = self.Chamber.getChamberNumber()
        isWrong = self.business.SlideTableToChamber(chamber_number=layer, isExit=False)
        if RECODE_SUCCEED == isWrong:
            self.axis_h.wait_empty_hook_return()
        self.business.status.setExit()

    def SlotEmptyHookReturnButton (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        self.axis_h.wait_empty_hook_return()
        pass

    def SlotQuitPLCLoopButton     (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return

        self.axis_h.set_h_force_quit()




    def SlotLowScanningSlide      (self):
        if not self.isAvailable():
            return
        if self.business.status.isRunning:
            return
        chamber_number  : int = self.Chamber.getChamberNumber()
        row_number      : int = self.Chamber.getTrayNumber ()
        if self.business.status.isExit:
            self.business.status.setRunning()
        self.business.status.SetTrayDetectorStatus(chamber_number=chamber_number, status=True)
        self.business.LowScanningTraySlide(chamber_number=chamber_number, row_number=row_number)
        self.business.status.setExit()

    def SlotHigScanningSlide      (self):
        if not self.isAvailable():
            return
        if self.business.status.isRunning:
            return
        chamber_number: int = self.Chamber.getChamberNumber()
        row_number: int = self.Chamber.getTrayNumber()
        if self.business.status.isExit:
            self.business.status.setRunning()
        self.business.status.SetTrayDetectorStatus(chamber_number=chamber_number, status=True)
        self.business.HigScanningTraySlide(chamber_number=chamber_number, row_number=row_number)
        self.business.status.setExit()

    def SlotScanningChamber(self):
        if not self.isAvailable():
            return
        if self.business.status.isRunning:
            return
        self.business.status.setExit()
        self.business.WaitDone(isAutoScanMode=True)
        pass

    def SlotScanningTray(self):
        if not self.isAvailable():
            return
        if self.business.status.isRunning:
            return
        chamber_number: int = self.Chamber.getChamberNumber()
        row_number: int = self.Chamber.getTrayNumber()
        self.business.status.InitChamberStatus()
        if self.business.status.isExit:
            self.business.status.setRunning()
        self.business.status.SetTraySlideDetectorStatus(chamber_number, row_number, True)
        CustomScanningModel.setTrayTemplate(chamber_number, None)
        self.business.WaitDone(isAutoScanMode=False)



    def SlotCheckTrayButton       (self):
        from AppCore.AppDBModels.ConfigModels.ChamberConfigModel import ChamberConfigModel
        if not self.isAvailable():
            return

        if not self.hasAxisH or not self.hasMicroscope:
            return
        if self.business.status.isRunning:
            return
        if self.business.status.isExit:
            self.business.status.setRunning()
        layer: int = self.Chamber.getChamberNumber()
        self.business.ChamberCheckTray(chamber_number=layer)
        self.business.status.setExit()

    def SlotCheckChamberButton    (self):
        from AppCore.AppDBModels.ConfigModels.ChamberConfigModel import ChamberConfigModel
        if not self.isAvailable():
            return
        if not self.hasAxisH or not self.hasMicroscope:
            return
        if self.business.status.isRunning:
            return
        if self.business.status.isExit:
            self.business.status.setRunning()
        layer: int = self.Chamber.getChamberNumber()
        self.business.ChamberCheck()
        self.business.status.setExit()

    def SlotPositionButton        (self):
        if not self.isAvailable():
            return
        if not self.hasMotion:
            return
        x: float
        y: float
        z: float
        h: float
        m: float
        isWrong, x, y, m = self.motion.get_scanning_position_xyz()
        if RECODE_SUCCEED == isWrong:
            self.Position.setXPosition(x)
            self.Position.setYPosition(y)
            self.Position.setMPosition(m)
        isWrong, objective = self.motion.microscope.get_objective()
        if RECODE_SUCCEED == isWrong:
            self.Chamber.setObjective(objective)

    def SlotYPlusButton        (self):
        if not self.isAvailable():
            return
        step: float = abs(self.Controller.get_step())
        self.axis_y.rel_waitmove(step)
        isWrong, value = self.axis_y.get_position()
        self.Position.setYPosition(value)

    def SlotYMinusButton       (self):
        if not self.isAvailable():
            return
        step: float = abs(self.Controller.get_step())
        self.axis_y.rel_waitmove(-step)
        isWrong, value = self.axis_y.get_position()
        self.Position.setYPosition(value)

    def SlotXPlusButton        (self):
        if not self.isAvailable():
            return
        step: float = abs(self.Controller.get_step())
        self.axis_x.rel_waitmove(step)
        isWrong, value = self.axis_x.get_position()
        self.Position.setXPosition(value)

    def SlotXMinusButton       (self):
        if not self.isAvailable():
            return
        step: float = abs(self.Controller.get_step())
        self.axis_x.rel_waitmove(-step)
        isWrong, value = self.axis_x.get_position()
        self.Position.setXPosition(value)

    def SlotZPlusButton        (self):
        if not self.isAvailable():
            return
        step: float = abs(self.Controller.get_step())
        self.axis_z.rel_waitmove(step)

    def SlotZMinusButton       (self):
        if not self.isAvailable():
            return
        step: float = abs(self.Controller.get_step())
        self.axis_z.rel_waitmove(-step)

    def SlotMicPlusButton      (self):
        if not self.isAvailable():
            return
        if not self.hasMicroscope:
            return
        step_value: float
        step: float = abs(self.Controller.get_microscope_step())
        unit: str = self.Controller.MicStepEdit.suffix()
        isWrong, step_convert_value = self.microscope.manager.get_step_count() # 步数单位为um
        if RECODE_SUCCEED != isWrong:
            return
        if self.business.system.isLeiCaMicroscope():
            if unit == 'mm':
                step_value = int(step * ( (1 * 1000) / step_convert_value))
            else:
                return

        else:
            if unit == 'mm':
                step_value = step * 1000000
            else:
                return
        self.microscope.rel_waitmove(abs(step_value))
        isWrong, value = self.microscope.get_position()
        self.Position.setMPosition(value)

    def SlotMicMinusButton     (self):
        if not self.isAvailable():
            return
        if not self.hasMicroscope:
            return
        if not self.isAvailable():
            return
        if not self.hasMicroscope:
            return
        step_value: float
        step: float = abs(self.Controller.get_microscope_step())
        unit: str = self.Controller.MicStepEdit.suffix()
        isWrong, step_convert_value = self.microscope.manager.get_step_count()  # 步数单位为um
        if RECODE_SUCCEED != isWrong:
            return
        if self.business.system.isLeiCaMicroscope():
            if unit == 'mm':
                step_value = int(step * ((1 * 1000) / step_convert_value))
            else:
                return

        else:
            if unit == 'mm':
                step_value = step * 1000000
            else:
                return
        self.microscope.rel_waitmove(-abs(step_value))
        isWrong, value = self.microscope.get_position()
        self.Position.setMPosition(value)

    def SlotHPlusButton        (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        status: int = self.axis_h.get_forward_status()
        self.axis_h.forward(not status)

    def SlotHMinusButton       (self):
        if not self.isAvailable():
            return

        status: int = self.axis_h.get_backward_status()
        self.axis_h.backward(not status)

    def SlotScanCodeButton     (self):
        if not self.isAvailable():
            return
        if not self.hasScanCode:
            return
        self.scancode.StartScanningCode()
        code_string: str = self.scancode.ReadScanningCode()
        print(code_string)


    def SlotCodeCompleteButton (self):
        if not self.isAvailable():
            return
        if not self.hasCamera or not self.hasCameraTimer:
            return
        if not self.CameraTimer.isActive():
            return
        if not self.camera.IsOpen:
            return
        from AppCore.DBModels import SlideFocusingModel

        item: SlideFocusingModel = SlideFocusingModel()
        self.initModel(item)
        self.camera.getFocusingNumpy(item=item, classifier=None)
        if item.hasImageSource:
            image = item.toImage()
            filename: str = AppUtils.absoluteFilePath(f"temp/{AppConvert.QDateTimeMsecToPath(item.CreateTime)}.png")
            from AppBackEnd.ProcessManager import ImageSaveProcess
            ImageSaveProcess(filename,  image.copy())
            print(f'{AppConvert.QDateTimeToString(Qt.QDateTime.currentDateTime())}\t{filename}')
            AppUtils.open_folder_safely(Qt.QFileInfo(filename).absolutePath())

    def initModel(self, model: SlideModelInterface):
        if not isinstance(model, SlideModelInterface):
            return
        x: float
        y: float
        z: float
        isWrong, x = self.manipulator.axis_x.get_position()
        isWrong, y = self.manipulator.axis_y.get_position()
        isWrong, z = self.microscope.get_position()
        chamber_number: int = self.Chamber.getChamberNumber()
        row_number: int = self.Chamber.getRowNumber()
        model.ChamberGroupNumber = chamber_number
        model.ChamberRowNumber = row_number
        model.XPosition = x
        model.YPosition = y
        model.zPosition = z
        model.CreateTime = Qt.QDateTime.currentDateTime().toPyDateTime()
        model.initCamera()



    def SlotCameraSwitch       (self):
        if not self.isAvailable():
            return
        self.initCameraTimer()
        if self.CameraTimer.isActive():
            self.CameraTimer.stop()
            if self.hasCamera:
                self.camera.StopGrabbing()
            self.CameraView.CameraView.SlotClearImageListSignal()
            return
        if not self.hasCamera:
            self.business.devices.initCamera()
        if not self.hasCamera:
            return
        level: int = self.Controller.ObjectiveEdit.value()
        if not self.camera.IsOpen:
            self.camera.ReOpen(level)
        if not self.camera.IsOpen:
            return
        self.camera.setModel(level)
        self.camera.StartGrabbing()
        if self.camera.IsGrabbing:
            self.CameraTimer.start(200)

    def SlotCameraTimer(self):
        if not self.hasCamera:
            return
        image: np.ndarray = self.camera.GetNumpyData()
        if image is None:
            return
        img  : Qt.QImage = ImageUtils.cv2_to_QImage(image)
        if img is None or img.isNull():
            return
        self.CameraView.CameraView.CameraUiSignal.emit(img, '')


    def SlotCameraButton       (self):
        if not self.hasCameraView:
            return
        if not self.CameraView.hasCameraView:
            return
        self.CameraView.CameraView.setCrosshair(not self.CameraView.CameraView.isCrosshair)

    def SlotDebugButton        (self):
        if not self.isAvailable():
            return
        if not self.hasDetection:
            return
        self.business.clearWarning()


    def SlotInitXYButton          (self):
        if not self.isAvailable:
            return
        if not self.hasManipulator:
            return
        self.manipulator.waithome_xy()
        self.Position.setXPosition(0)
        self.Position.setYPosition(0)

    def SlotInitZButton           (self):
        if not self.isAvailable:
            return
        if not self.hasManipulator:
            return
        self.manipulator.waithome_z()

    def SlotInitHButton           (self):
        if not self.isAvailable:
            return
        if not self.hasManipulator:
            return
        if not self.axis_h.isAvailable:
            self.manipulator.initManager()
        self.axis_h.wait_empty_hook_return()

    def SlotInitMicButton         (self):
        if not self.isAvailable:
            return
        if not self.hasManipulator:
            return
        self.microscope.waithome()
        isWrong, position = self.microscope.get_position()
        self.Position.setMPosition(position)
        isWrong, objective = self.microscope.get_objective()
        self.Chamber.setObjective(objective)

    def SlotInitCodeButton        (self):
        if not self.isAvailable:
            return
        if not self.hasManipulator:
            return
        self.scancode.waithome()

    def SlotInitCameraButton      (self):
        if not self.isAvailable:
            return
        if not self.hasManipulator:
            return

        self.camera.waithome()


    def SlotObjectiveEdit(self):
        if not self.isAvailable():
            return
        if not self.hasMicroscope:
            return
        if not self.microscope.isAvailable:
            self.microscope.ReOpen()
        if self.microscope.isAvailable:
            objective: int = self.Controller.get_objective_value()
            self.microscope.set_objective(objective)
            self.Chamber.setObjective(objective)

    def SlotOilButton(self):
        if not self.isAvailable():
            return
        if not self.hasManipulator:
            return
        if not self.hasDetection:
            return
        enable: bool = self.Controller.isOilEnabled()
        from AppCore.DBModels import AnointingModel
        config: AnointingModel = AnointingModel.getConfig(ObjectiveLevel.Objective1)
        self.detection.set_oil_speed(config.OilDropingSpeed)
        is_enable: bool = not enable
        isWrong = self.detection.oil_switch(is_enable)
        if RECODE_SUCCEED == isWrong:
            self.Controller.setOilEnabled(is_enable)


    @property
    def hasCameraTimer(self) -> bool:
        return hasattr(self, 'CameraTimer') and isinstance(self.CameraTimer, Qt.QTimer)