Example #1
0
def module_setup_teardown(qtbot):
    global ui, widget, Test, Test1, app

    class Test1:
        threadPool = QThreadPool()

    class Test(QObject):
        config = {'mainW': {}}
        messageQueue = Queue()
        threadPool = QThreadPool()
        update1s = pyqtSignal()
        power = PegasusUPB(app=Test1())

    widget = QWidget()
    ui = Ui_MainWindow()
    ui.setupUi(widget)

    app = Power(app=Test(),
                ui=ui,
                clickable=MWidget().clickable,
                change=MWidget().changeStyleDynamic)
    app.close = MWidget().close
    app.deleteLater = MWidget().deleteLater
    qtbot.addWidget(app)

    yield

    del widget, ui, Test, Test1, app
def module_setup_teardown(qtbot):
    global ui, widget, Test, Test1, app

    class Test1(QObject):
        mount = Mount()
        update1s = pyqtSignal()
        update10s = pyqtSignal()
        threadPool = QThreadPool()

    class Test(QObject):
        config = {'mainW': {}}
        threadPool = QThreadPool()
        update1s = pyqtSignal()
        message = pyqtSignal(str, int)
        mount = Mount()
        mount.obsSite.location = Topos(latitude_degrees=20,
                                       longitude_degrees=10,
                                       elevation_m=500)
        sensorWeather = SensorWeather(app=Test1())
        onlineWeather = OnlineWeather(app=Test1())
        directWeather = DirectWeather(app=Test1())
        skymeter = Skymeter(app=Test1())
        cover = FlipFlat(app=Test1())
        filter = Filter(app=Test1())
        camera = Camera(app=Test1())
        focuser = Focuser(app=Test1())
        dome = Dome(app=Test1())
        power = PegasusUPB(app=Test1())
        astrometry = Astrometry(app=Test1())
        relay = KMRelay()
        measure = MeasureData(app=Test1())
        remote = Remote(app=Test1())
        telescope = Telescope(app=Test1())

    widget = QWidget()
    ui = Ui_MainWindow()
    ui.setupUi(widget)

    app = SettDevice(app=Test(), ui=ui,
                     clickable=MWidget().clickable,
                     change=MWidget().changeStyleDynamic)
    app.close = MWidget().close
    app.deleteLater = MWidget().deleteLater
    app.deviceStat = dict()
    app.log = CustomLogger(logging.getLogger(__name__), {})
    app.threadPool = QThreadPool()
    app.config = dict()
    app.BACK_NORM = '#000000'

    qtbot.addWidget(app)

    yield

    del widget, ui, Test, Test1, app
Example #3
0
def module_setup_teardown(qtbot):
    global ui, widget, Test, Test1, app

    class Test1(QObject):
        mount = Mount()
        update10s = pyqtSignal()
        threadPool = QThreadPool()

    class Test(QObject):
        config = {'mainW': {}}
        threadPool = QThreadPool()
        update1s = pyqtSignal()
        update30m = pyqtSignal()
        message = pyqtSignal(str, int)
        mount = Mount()
        mount.obsSite.location = Topos(latitude_degrees=20,
                                       longitude_degrees=10,
                                       elevation_m=500)
        sensorWeather = SensorWeather(app=Test1())
        onlineWeather = OnlineWeather(app=Test1())
        skymeter = Skymeter(app=Test1())

    widget = QWidget()
    ui = Ui_MainWindow()
    ui.setupUi(widget)

    app = EnvironGui(app=Test(),
                     ui=ui,
                     clickable=MWidget().clickable,
                     change=MWidget().changeStyleDynamic)
    app.close = MWidget().close
    app.deleteLater = MWidget().deleteLater
    app.deviceStat = dict()
    app.log = CustomLogger(logging.getLogger(__name__), {})
    app.threadPool = QThreadPool()

    qtbot.addWidget(app)

    yield

    del widget, ui, Test, Test1, app
Example #4
0
    def __init__(self, app):
        self.app = app
        self.threadPool = app.threadPool
        super().__init__()

        # load and init the gui
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.initUI()
        self.setupIcons()
        self.setWindowTitle(f'MountWizzard4 - v{self.app.__version__}')

        self.deviceStat = {
            'dome': None,
            'mount': None,
            'camera': None,
            'astrometry': None,
            'environOverall': None,
            'sensorWeather': None,
            'directWeather': None,
            'onlineWeather': None,
            'skymeter': None,
            'cover': None,
            'telescope': None,
            'power': None,
            'remote': None,
            'relay': None,
            'measure': None,
        }

        # setting device stats in measurement task
        # todo: better place and decision if position is good
        self.app.measure.deviceStat = self.deviceStat

        self.deviceStatGui = {
            'dome': self.ui.domeConnected,
            'camera': self.ui.cameraConnected,
            'environOverall': self.ui.environConnected,
            'astrometry': self.ui.astrometryConnected,
            'mount': self.ui.mountConnected
        }

        self.mwSuper('__init__')

        # polarPlot ui instance has to be defined central, not in the mixins
        self.polarPlot = self.embedMatplot(self.ui.modelPolar)

        # connect signals for refreshing the gui
        self.app.mount.signals.pointDone.connect(self.updateStatusGUI)
        self.app.mount.signals.mountUp.connect(self.updateMountConnStat)
        self.app.mount.signals.settingDone.connect(self.updateMountWeatherStat)
        self.app.remoteCommand.connect(self.remoteCommand)
        self.app.astrometry.signals.message.connect(
            self.updateAstrometryStatus)
        self.app.dome.signals.message.connect(self.updateDomeStatus)
        self.app.camera.signals.message.connect(self.updateCameraStatus)
        self.app.onlineWeather.signals.connected.connect(
            self.updateOnlineWeatherStat)

        # connect gui signals
        self.ui.saveConfigQuit.clicked.connect(self.quitSave)
        self.ui.loadFrom.clicked.connect(self.loadProfile)
        self.ui.saveConfigAs.clicked.connect(self.saveProfileAs)
        self.ui.saveConfig.clicked.connect(self.saveProfile)

        # initial call for writing the gui
        self.initConfig()

        # cyclic updates
        self.app.update1s.connect(self.updateTime)
        self.app.update1s.connect(self.updateWindowsStats)
        self.app.update1s.connect(self.smartFunctionGui)
        self.app.update1s.connect(self.smartTabGui)
        self.app.update1s.connect(self.smartEnvironGui)
        self.app.update1s.connect(self.updateWindowsStats)
        self.app.update1s.connect(self.updateDeviceStats)
Example #5
0
class MainWindow(
        MWidget,
        Mount,
        EnvironGui,
        Model,
        BuildPoints,
        ManageModel,
        Satellite,
        Relay,
        Power,
        Tools,
        SettDevice,
        SettMount,
        SettHorizon,
        SettImaging,
        SettParkPos,
        SettRelay,
        SettMisc,
):
    """
    the main window class handles the main menu as well as the show and no show part of
    any other window. all necessary processing for functions of that gui will be linked
    to this class. therefore window classes will have a threadpool for managing async
    processing if needed.
    """

    __all__ = [
        'MainWindow',
    ]

    logger = logging.getLogger(__name__)
    log = CustomLogger(logger, {})

    def __init__(self, app):
        self.app = app
        self.threadPool = app.threadPool
        super().__init__()

        # load and init the gui
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.initUI()
        self.setupIcons()
        self.setWindowTitle(f'MountWizzard4 - v{self.app.__version__}')

        self.deviceStat = {
            'dome': None,
            'mount': None,
            'camera': None,
            'astrometry': None,
            'environOverall': None,
            'sensorWeather': None,
            'directWeather': None,
            'onlineWeather': None,
            'skymeter': None,
            'cover': None,
            'telescope': None,
            'power': None,
            'remote': None,
            'relay': None,
            'measure': None,
        }

        # setting device stats in measurement task
        # todo: better place and decision if position is good
        self.app.measure.deviceStat = self.deviceStat

        self.deviceStatGui = {
            'dome': self.ui.domeConnected,
            'camera': self.ui.cameraConnected,
            'environOverall': self.ui.environConnected,
            'astrometry': self.ui.astrometryConnected,
            'mount': self.ui.mountConnected
        }

        self.mwSuper('__init__')

        # polarPlot ui instance has to be defined central, not in the mixins
        self.polarPlot = self.embedMatplot(self.ui.modelPolar)

        # connect signals for refreshing the gui
        self.app.mount.signals.pointDone.connect(self.updateStatusGUI)
        self.app.mount.signals.mountUp.connect(self.updateMountConnStat)
        self.app.mount.signals.settingDone.connect(self.updateMountWeatherStat)
        self.app.remoteCommand.connect(self.remoteCommand)
        self.app.astrometry.signals.message.connect(
            self.updateAstrometryStatus)
        self.app.dome.signals.message.connect(self.updateDomeStatus)
        self.app.camera.signals.message.connect(self.updateCameraStatus)
        self.app.onlineWeather.signals.connected.connect(
            self.updateOnlineWeatherStat)

        # connect gui signals
        self.ui.saveConfigQuit.clicked.connect(self.quitSave)
        self.ui.loadFrom.clicked.connect(self.loadProfile)
        self.ui.saveConfigAs.clicked.connect(self.saveProfileAs)
        self.ui.saveConfig.clicked.connect(self.saveProfile)

        # initial call for writing the gui
        self.initConfig()

        # cyclic updates
        self.app.update1s.connect(self.updateTime)
        self.app.update1s.connect(self.updateWindowsStats)
        self.app.update1s.connect(self.smartFunctionGui)
        self.app.update1s.connect(self.smartTabGui)
        self.app.update1s.connect(self.smartEnvironGui)
        self.app.update1s.connect(self.updateWindowsStats)
        self.app.update1s.connect(self.updateDeviceStats)

    def mwSuper(self, func):
        """
        mwSuper is a replacement for super() to manage the mixin style of implementation
        it's not an ideal way to do it, but mwSuper() call the method of every ! parent
        class if they exist.

        :param func:
        :return: true for test purpose
        """

        for base in self.__class__.__bases__:
            if base.__name__ == 'MWidget':
                continue
            if hasattr(base, func):
                funcAttrib = getattr(base, func)
                funcAttrib(self)
        return True

    def initConfig(self):
        """
        initConfig read the key out of the configuration dict and stores it to the gui
        elements. if some initialisations have to be proceeded with the loaded persistent
        data, they will be launched as well in this method.

        :return: True for test purpose
        """

        config = self.app.config
        self.ui.profile.setText(config.get('profileName'))
        if 'mainW' not in config:
            config['mainW'] = {}
        config = config['mainW']
        x = config.get('winPosX', 100)
        y = config.get('winPosY', 100)
        if x > self.screenSizeX:
            x = 0
        if y > self.screenSizeY:
            y = 0
        self.move(x, y)
        self.ui.mainTabWidget.setCurrentIndex(config.get('mainTabWidget', 0))
        self.ui.settingsTabWidget.setCurrentIndex(
            config.get('settingsTabWidget', 0))

        # todo: remove analysis tab while not developed
        tabWidget = self.ui.mainTabWidget.findChild(PyQt5.QtWidgets.QWidget,
                                                    'Analyse')
        tabIndex = self.ui.mainTabWidget.indexOf(tabWidget)
        self.ui.mainTabWidget.setTabEnabled(tabIndex, False)
        self.ui.mainTabWidget.setStyleSheet(self.getStyle())

        self.mwSuper('initConfig')
        self.changeStyleDynamic(self.ui.mountConnected, 'color', 'gray')

        return True

    def storeConfig(self):
        """
        storeConfig writes the keys to the configuration dict and stores. if some
        saving has to be proceeded to persistent data, they will be launched as
        well in this method.

        :return: True for test purpose
        """

        config = self.app.config
        config['profileName'] = self.ui.profile.text()
        if 'mainW' not in config:
            config['mainW'] = {}
        config = config['mainW']
        config['winPosX'] = self.pos().x()
        config['winPosY'] = self.pos().y()
        config['mainTabWidget'] = self.ui.mainTabWidget.currentIndex()
        config['settingsTabWidget'] = self.ui.settingsTabWidget.currentIndex()

        self.mwSuper('storeConfig')
        return True

    def closeEvent(self, closeEvent):
        """
        we overwrite the close event of the window just for the main window to close the
        application as well. because it does not make sense to have child windows open if
        main is already closed.

        :return:    nothing
        """
        # remove waiting todo: better place ?
        self.changeStyleDynamic(self.ui.pauseModel, 'pause', False)

        super().closeEvent(closeEvent)
        self.close()
        self.app.quit()

    def quitSave(self):
        """
        quitSave finished up and calls the quit save function in main for saving the parameters


        :return:    nothing
        """
        # remove waiting todo: better place ?
        self.changeStyleDynamic(self.ui.pauseModel, 'pause', False)
        self.app.quitSave()

    def setupIcons(self):
        """
        setupIcons add icon from standard library to certain buttons for improving the
        gui of the app.

        :return:    True if success for test
        """

        self.wIcon(self.ui.saveConfigAs,
                   PyQt5.QtWidgets.QStyle.SP_DialogSaveButton)
        self.wIcon(self.ui.loadFrom, PyQt5.QtWidgets.QStyle.SP_DirOpenIcon)
        self.wIcon(self.ui.saveConfig,
                   PyQt5.QtWidgets.QStyle.SP_DialogSaveButton)
        self.wIcon(self.ui.saveConfigQuit,
                   PyQt5.QtWidgets.QStyle.SP_DialogSaveButton)
        self.wIcon(self.ui.runFlexure,
                   PyQt5.QtWidgets.QStyle.SP_DialogApplyButton)
        self.wIcon(self.ui.runHysteresis,
                   PyQt5.QtWidgets.QStyle.SP_DialogApplyButton)
        self.wIcon(self.ui.cancelAnalyse,
                   PyQt5.QtWidgets.QStyle.SP_DialogCancelButton)

        self.wIcon(self.ui.plateSolveSync,
                   PyQt5.QtWidgets.QStyle.SP_DialogApplyButton)
        pixmap = PyQt5.QtGui.QPixmap(':/pics/azimuth1.png')
        self.ui.picAZ.setPixmap(pixmap)
        pixmap = PyQt5.QtGui.QPixmap(':/pics/altitude1.png')
        self.ui.picALT.setPixmap(pixmap)
        pixmap = PyQt5.QtGui.QPixmap(':/pics/offset.png').scaled(301, 301)
        self.ui.picDome1.setPixmap(pixmap)

        self.wIcon(self.ui.cancelModel,
                   PyQt5.QtWidgets.QStyle.SP_DialogCancelButton)
        self.wIcon(self.ui.runModel,
                   PyQt5.QtWidgets.QStyle.SP_DialogApplyButton)

        self.wIcon(self.ui.genBuildGrid,
                   PyQt5.QtWidgets.QStyle.SP_DialogApplyButton)
        self.wIcon(self.ui.genBuildMax,
                   PyQt5.QtWidgets.QStyle.SP_DialogApplyButton)
        self.wIcon(self.ui.genBuildMed,
                   PyQt5.QtWidgets.QStyle.SP_DialogApplyButton)
        self.wIcon(self.ui.genBuildNorm,
                   PyQt5.QtWidgets.QStyle.SP_DialogApplyButton)
        self.wIcon(self.ui.genBuildGrid,
                   PyQt5.QtWidgets.QStyle.SP_DialogApplyButton)
        self.wIcon(self.ui.genBuildSpiralMax,
                   PyQt5.QtWidgets.QStyle.SP_DialogApplyButton)
        self.wIcon(self.ui.genBuildSpiralMed,
                   PyQt5.QtWidgets.QStyle.SP_DialogApplyButton)
        self.wIcon(self.ui.genBuildSpiralNorm,
                   PyQt5.QtWidgets.QStyle.SP_DialogApplyButton)
        self.wIcon(self.ui.genBuildSpiralMin,
                   PyQt5.QtWidgets.QStyle.SP_DialogApplyButton)
        self.wIcon(self.ui.genBuildDSO,
                   PyQt5.QtWidgets.QStyle.SP_DialogApplyButton)

        self.wIcon(self.ui.runTargetRMS,
                   PyQt5.QtWidgets.QStyle.SP_DialogApplyButton)
        self.wIcon(self.ui.cancelTargetRMS,
                   PyQt5.QtWidgets.QStyle.SP_DialogCancelButton)
        self.wIcon(self.ui.loadName, PyQt5.QtWidgets.QStyle.SP_DirOpenIcon)
        self.wIcon(self.ui.saveName,
                   PyQt5.QtWidgets.QStyle.SP_DialogSaveButton)
        self.wIcon(self.ui.deleteName, PyQt5.QtWidgets.QStyle.SP_TrashIcon)
        self.wIcon(self.ui.refreshName,
                   PyQt5.QtWidgets.QStyle.SP_BrowserReload)
        self.wIcon(self.ui.refreshModel,
                   PyQt5.QtWidgets.QStyle.SP_BrowserReload)

        self.wIcon(self.ui.stop, PyQt5.QtWidgets.QStyle.SP_MessageBoxWarning)

        self.wIcon(self.ui.mountOn,
                   PyQt5.QtWidgets.QStyle.SP_DialogApplyButton)
        self.wIcon(self.ui.mountOff,
                   PyQt5.QtWidgets.QStyle.SP_MessageBoxCritical)
        self.wIcon(self.ui.renameStart,
                   PyQt5.QtWidgets.QStyle.SP_DialogApplyButton)

        return True

    def updateMountConnStat(self, status):
        """
        updateMountConnStat show the connection status of the mount. if status is None,
        which means there is no valid host entry for connection, the status is grey

        :param status:
        :return: true for test purpose
        """

        self.deviceStat['mount'] = status
        return True

    def updateMountWeatherStat(self, setting):
        """
        updateMountWeatherStat show the connection status of the mount weather station
        connected. if the data values are None there is no station attached to the
        GPS port,

        :return: true for test purpose
        """

        if setting.weatherTemperature is None and setting.weatherPressure is None:
            self.deviceStat['directWeather'] = None
        else:
            if setting.weatherStatus is None:
                self.deviceStat['directWeather'] = False
            else:
                self.deviceStat['directWeather'] = True
        return True

    def smartFunctionGui(self):
        """
        smartFunctionGui enables and disables gui actions depending on the actual state of the
        different devices. this should be the core of avoiding user misused during running
        operations. smartGui is run every 1 second synchronously, because it can't be
        simpler done with dynamic approach. all different situations in a running
        environment is done locally.

        :return: true for test purpose
        """

        # check if modeling would work (mount + solve + image)
        isReady = all(self.deviceStat[x]
                      for x in ['mount', 'camera', 'astrometry'])
        if isReady and self.app.data.buildP:
            self.ui.runModel.setEnabled(True)
            self.ui.plateSolveSync.setEnabled(True)
            self.ui.runFlexure.setEnabled(True)
            self.ui.runHysteresis.setEnabled(True)
        else:
            self.ui.runModel.setEnabled(False)
            self.ui.plateSolveSync.setEnabled(False)
            self.ui.runFlexure.setEnabled(False)
            self.ui.runHysteresis.setEnabled(False)

        # if mount is not up, you cannot program a model
        if self.deviceStat.get('mount', False):
            self.ui.batchModel.setEnabled(True)
        else:
            self.ui.batchModel.setEnabled(False)

        stat = self.deviceStat.get('environOverall', None)
        if stat is None:
            self.ui.refractionGroup.setEnabled(False)
            self.ui.setRefractionManual.setEnabled(False)
        elif stat and self.deviceStat.get('mount', None):
            self.ui.refractionGroup.setEnabled(True)
            self.ui.setRefractionManual.setEnabled(True)
        else:
            self.ui.refractionGroup.setEnabled(False)
            self.ui.setRefractionManual.setEnabled(False)

        return True

    def smartTabGui(self):
        """
        smartTabGui enables and disables tab visibility depending on the actual state of the
        different devices.
        :return: true for test purpose
        """

        smartTabs = {
            'ManageModel': {
                'statID': 'mount',
                'tab': self.ui.mainTabWidget,
            },
            'Power': {
                'statID': 'power',
                'tab': self.ui.mainTabWidget,
            },
            'Relay': {
                'statID': 'relay',
                'tab': self.ui.mainTabWidget,
            },
            'KMTronic': {
                'statID': 'relay',
                'tab': self.ui.settingsTabWidget,
            },
        }

        tabChanged = False

        for key, tab in smartTabs.items():
            # finding the right tab and get the status
            tabWidget = smartTabs[key]['tab'].findChild(
                PyQt5.QtWidgets.QWidget, key)
            tabIndex = smartTabs[key]['tab'].indexOf(tabWidget)
            tabStatus = smartTabs[key]['tab'].isTabEnabled(tabIndex)

            # determine the new stat, set it and check if changed
            stat = bool(self.deviceStat.get(smartTabs[key]['statID']))
            smartTabs[key]['tab'].setTabEnabled(tabIndex, stat)
            tabChanged = tabChanged or (tabStatus != stat)

        # redraw tabs only when a change occurred. this is necessary, because
        # enable and disable does not remove tabs
        if tabChanged:
            # todo: the only better change is to remove the tab and insert the tab back.
            self.ui.mainTabWidget.setStyleSheet(self.getStyle())
            self.ui.settingsTabWidget.setStyleSheet(self.getStyle())

        return True

    def smartEnvironGui(self):
        """
        smartEnvironGui enables and disables gui actions depending on the actual state
        of the different environment devices. it is run every 1 second synchronously,
        because it can't be simpler done with dynamic approach. all different situations
        in a running environment is done locally.

        :return: true for test purpose
        """

        environ = {
            'directWeather': self.ui.directWeatherGroup,
            'sensorWeather': self.ui.sensorWeatherGroup,
            'onlineWeather': self.ui.onlineWeatherGroup,
            'skymeter': self.ui.skymeterGroup,
            'power': self.ui.powerGroup,
        }

        for key, group in environ.items():
            stat = self.deviceStat.get(key, None)
            if stat is None:
                group.setFixedWidth(0)
                group.setEnabled(False)
            elif stat:
                group.setMinimumSize(75, 0)
                group.setEnabled(True)
            else:
                group.setMinimumSize(75, 0)
                group.setEnabled(False)

        return True

    def updateWindowsStats(self):
        """

        :return: True for test purpose
        """

        for win in self.app.uiWindows:
            winObj = self.app.uiWindows[win]
            if winObj['classObj']:
                self.changeStyleDynamic(winObj['button'], 'running', True)
            else:
                self.changeStyleDynamic(winObj['button'], 'running', False)

        return True

    def updateDeviceStats(self):
        """
        updateDeviceStats sets the colors in main window upper bar for getting
        important overview, which functions are available.

        the refraction sources etc are defined in tabEnviron, but it is optimal
        setting the selected source right at this point as it is synchronous if
        state is switching

        :return: True for test purpose
        """

        if self.refractionSource in self.deviceStat:
            self.deviceStat['environOverall'] = self.deviceStat[
                self.refractionSource]
        else:
            self.deviceStat['environOverall'] = None

        for device, ui in self.deviceStatGui.items():
            if self.deviceStat.get(device, None) is None:
                self.changeStyleDynamic(ui, 'color', 'gray')
            elif self.deviceStat[device]:
                self.changeStyleDynamic(ui, 'color', 'green')
            else:
                self.changeStyleDynamic(ui, 'color', 'red')

        return True

    def updateOnlineWeatherStat(self, stat):
        """
        updateOnlineWeatherStat receives a signal when online weather changes the status
        and stores it

        :param stat:
        :return: True for test purpose
        """

        self.deviceStat['onlineWeather'] = stat

        return True

    def updateTime(self):
        """
        updateTime updates the time display in gui, show the actual thread count an the
        online status set

        :return: success
        """

        self.ui.timeComputer.setText(
            datetime.datetime.now().strftime('%H:%M:%S'))
        if self.ui.isOnline.isChecked():
            text = 'Internet Online Mode'
        else:
            text = 'Offline Mode'
        text = f'{self.threadPool.activeThreadCount():2d} - {text}'
        self.ui.statusOnline.setTitle(text)

    def updateAstrometryStatus(self, text):
        """

        :param text:
        :return: true for test purpose
        """

        self.ui.astrometryText.setText(text)
        return True

    def updateDomeStatus(self, text):
        """

        :param text:
        :return: true for test purpose
        """

        self.ui.domeText.setText(text)
        return True

    def updateCameraStatus(self, text):
        """

        :param text:
        :return: true for test purpose
        """

        self.ui.cameraText.setText(text)
        return True

    def updateStatusGUI(self, obs):
        """
        updateStatusGUI update the gui upon events triggered be the reception of new data
        from the mount. the mount data is polled, so we use this signal as well for the
        update process.

        :return:    True if ok for testing
        """

        if obs.statusText() is not None:
            self.ui.statusText.setText(obs.statusText())
        else:
            self.ui.statusText.setText('-')

        if self.app.mount.obsSite.status == 0:
            self.changeStyleDynamic(self.ui.tracking, 'running', 'true')
        else:
            self.changeStyleDynamic(self.ui.tracking, 'running', 'false')

        if self.app.mount.obsSite.status == 5:
            self.changeStyleDynamic(self.ui.park, 'running', 'true')
        else:
            self.changeStyleDynamic(self.ui.park, 'running', 'false')

        if self.app.mount.obsSite.status == 1:
            self.changeStyleDynamic(self.ui.stop, 'running', 'true')
        else:
            self.changeStyleDynamic(self.ui.stop, 'running', 'false')

        return True

    @staticmethod
    def checkExtension(filePath, ext):
        """

        :param filePath:
        :param ext:
        :return:
        """

        if not filePath.endswith(ext):
            filePath += ext
        return filePath

    def loadProfile(self):
        """

        :return:
        """

        folder = self.app.mwGlob['configDir']
        loadFilePath, name, ext = self.openFile(
            self,
            'Open config file',
            folder,
            'Config files (*.cfg)',
            enableDir=False,
        )
        if not name:
            return False
        suc = self.app.loadConfig(name=name)
        if suc:
            self.ui.profile.setText(name)
            self.app.message.emit('Profile: [{0}] loaded'.format(name), 0)
        else:
            self.app.message.emit(
                'Profile: [{0}] cannot no be loaded'.format(name), 2)
        return True

    def saveProfileAs(self):
        """

        :return:
        """

        folder = self.app.mwGlob['configDir']
        saveFilePath, name, ext = self.saveFile(
            self,
            'Save config file',
            folder,
            'Config files (*.cfg)',
            enableDir=False,
        )
        if not name:
            return False
        self.app.storeConfig()
        self.app.config['profileName'] = name
        suc = self.app.saveConfig(name=name)
        if suc:
            self.ui.profile.setText(name)
            self.app.message.emit('Profile: [{0}] saved'.format(name), 0)
        else:
            self.app.message.emit(
                'Profile: [{0}] cannot no be saved'.format(name), 2)
        return True

    def saveProfile(self):
        """
        saveProfile calls save profile in main and sends a message to the user about
        success.

        :return: nothing
        """

        self.app.storeConfig()
        suc = self.app.saveConfig()
        if suc:
            self.app.message.emit('Actual profile saved', 0)
        else:
            self.app.message.emit('Actual profile cannot not be saved', 2)
        return suc

    def remoteCommand(self, command):
        """

        :param command:
        :return:
        """

        if command == 'shutdown':
            self.app.quitSave()
            self.app.message.emit('Shutdown MW remotely', 2)
        elif command == 'shutdown mount':
            self.mountShutdown()
            self.app.message.emit('Shutdown mount remotely', 2)
        elif command == 'boot mount':
            self.mountBoot()
            self.app.message.emit('Boot mount remotely', 2)