Beispiel #1
0
    def test_show(self):

        if not QtWidgets.QApplication.instance():
            QtWidgets.QApplication([])

        mw = QtWidgets.QMainWindow()

        t = InfoTab(main_win=mw,
                    lib_info=LibInfo(),
                    app_info=AppInfo(),
                    with_online_manual=True,
                    with_offline_manual=True,
                    with_bug_report=True,
                    with_hydroffice_link=True,
                    with_ccom_link=True,
                    with_noaa_link=True,
                    with_unh_link=True,
                    with_license=True)
        t.show()
Beispiel #2
0
        sys.exit(app.exit())

mw = QtWidgets.QMainWindow()
mw.setObjectName(app_info.app_main_window_object_name)
mw.setWindowTitle('%s v.%s' % (app_info.app_name, app_info.app_version))
mw.setWindowIcon(QtGui.QIcon(app_info.app_icon_path))

tabs = QtWidgets.QTabWidget()
mw.setCentralWidget(tabs)

t = InfoTab(app_info=app_info,
            lib_info=lib_info,
            with_online_manual=True,
            with_offline_manual=True,
            with_bug_report=True,
            with_hydroffice_link=True,
            with_ccom_link=True,
            with_noaa_link=True,
            with_unh_link=True,
            with_license=True,
            with_noaa_57=True,
            main_win=mw)

tabs.insertTab(0, t, "Info")

mw.show()

# print("browser storage: %s" % t.browser.view.page().profile().persistentStoragePath())

sys.exit(app.exec_())
Beispiel #3
0
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)

        logger.info("* > APP: initializing ...")

        # set the application name and the version
        self.name = app_info.app_name
        self.version = app_info.app_version
        self.setWindowTitle('%s v.%s' % (self.name, self.version))
        # noinspection PyArgumentList
        _app = QtCore.QCoreApplication.instance()
        _app.setApplicationName('%s' % self.name)
        _app.setOrganizationName("HydrOffice")
        _app.setOrganizationDomain("hydroffice.org")

        # set the minimum and the initial size
        self.setMinimumSize(640, 480)
        self.resize(920, 640)

        # set icons
        self.setWindowIcon(QtGui.QIcon(app_info.app_icon_path))

        # check if setup db exists; if yes, ask to copy
        has_setup = SoundSpeedLibrary.setup_exists()
        logger.info("setup exists: %s" % has_setup)
        if not has_setup:
            other_setups = SoundSpeedLibrary.list_other_setups()
            if len(other_setups) != 0:
                logger.debug("other existing setups: %d" % len(other_setups))
                # noinspection PyCallByClass
                sel, ok = QtWidgets.QInputDialog.getItem(self, 'Do you want to copy an existing setup?',
                                                         'Select one (or click on Cancel to create a new one):',
                                                         other_setups, 0, False)
                if ok:
                    SoundSpeedLibrary.copy_setup(input_setup=sel)

        # create the project
        self.lib = SoundSpeedLibrary(callbacks=QtCallbacks(parent=self), progress=QtProgress(parent=self))
        logger.info("current configuration:\n%s" % Helper(lib_info=lib_info).package_info())
        self.check_woa09()
        self.check_woa13()
        # self.check_rtofs()  # no need to wait for the download at the beginning
        self.check_sis4()
        self.check_sis5()
        self.check_sippican()
        self.check_mvp()

        # init default settings
        settings = QtCore.QSettings()
        export_folder = settings.value("export_folder")
        if (export_folder is None) or (not os.path.exists(export_folder)):
            settings.setValue("export_folder", self.lib.data_folder)
        import_folder = settings.value("import_folder")
        if (import_folder is None) or (not os.path.exists(import_folder)):
            settings.setValue("import_folder", self.lib.data_folder)

        # menu

        self.menu = self.menuBar()
        self.file_menu = self.menu.addMenu("File")
        self.edit_menu = self.menu.addMenu("Process")
        self.database_menu = self.menu.addMenu("Database")
        self.monitor_menu = self.menu.addMenu("Monitor")
        self.server_menu = self.menu.addMenu("Server")
        self.setup_menu = self.menu.addMenu("Setup")
        self.help_menu = self.menu.addMenu("Help")

        # make tabs
        self.tabs = QtWidgets.QTabWidget()
        self.setCentralWidget(self.tabs)
        self.tabs.setIconSize(QtCore.QSize(42, 42))
        self.tabs.blockSignals(True)  # during the initialization
        # noinspection PyUnresolvedReferences
        self.tabs.currentChanged.connect(self.on_change)  # changed!
        # editor
        self.tab_editor = Editor(lib=self.lib, main_win=self)
        self.idx_editor = self.tabs.insertTab(0, self.tab_editor,
                                              QtGui.QIcon(os.path.join(app_info.app_media_path, 'editor.png')), "")
        self.tabs.setTabToolTip(self.idx_editor, "Editor")
        # database
        self.tab_database = Database(lib=self.lib, main_win=self)
        self.idx_database = self.tabs.insertTab(1, self.tab_database,
                                                QtGui.QIcon(os.path.join(app_info.app_media_path, 'database.png')), "")
        self.tabs.setTabToolTip(self.idx_database, "Database")
        # survey data monitor
        self.has_sdm_support = True
        try:  # try.. except to make SSM working also without SDM
            # noinspection PyUnresolvedReferences
            from hyo2.surveydatamonitor.app.widgets.monitor import SurveyDataMonitor
            self.tab_monitor = SurveyDataMonitor(lib=self.lib, main_win=self)
            self.idx_monitor = self.tabs.insertTab(3, self.tab_monitor,
                                                   QtGui.QIcon(
                                                       os.path.join(app_info.app_media_path, 'surveydatamonitor.png')),
                                                   "")
            self.tabs.setTabToolTip(self.idx_monitor, "Survey Data Monitor")
            logger.info("Support for Survey Monitor: ON")
        except Exception as e:
            traceback.print_exc()
            self.has_sdm_support = False
            logger.info("Support for Survey Monitor: OFF(%s)" % e)
        # server
        self.tab_server = Server(lib=self.lib, main_win=self)
        self.idx_server = self.tabs.insertTab(4, self.tab_server,
                                              QtGui.QIcon(os.path.join(app_info.app_media_path, 'server.png')), "")
        self.tabs.setTabToolTip(self.idx_server, "Synthetic Profile Server")

        # refraction
        # self.tab_refraction = Refraction(lib=self.lib, main_win=self)
        # idx = self.tabs.insertTab(5, self.tab_refraction,
        #                           QtGui.QIcon(os.path.join(app_info.app_media_path, 'refraction.png')), "")
        # self.tabs.setTabToolTip(idx, "Refraction Monitor")
        # setup
        self.tab_setup = Settings(lib=self.lib, main_win=self)
        self.idx_setup = self.tabs.insertTab(6, self.tab_setup,
                                             QtGui.QIcon(os.path.join(app_info.app_media_path, 'settings.png')), "")
        self.tabs.setTabToolTip(self.idx_setup, "Setup")
        # info
        self.tab_info = InfoTab(main_win=self, lib_info=lib_info, app_info=app_info,
                                with_online_manual=True,
                                with_offline_manual=True,
                                with_bug_report=True,
                                with_hydroffice_link=True,
                                with_ccom_link=True,
                                with_noaa_link=True,
                                with_unh_link=True,
                                with_license=True)
        self.idx_info = self.tabs.insertTab(6, self.tab_info,
                                            QtGui.QIcon(os.path.join(app_info.app_media_path, 'info.png')), "")
        self.tabs.setTabToolTip(self.idx_info, "Info")
        # Help menu
        self.help_menu.addAction(self.tab_info.open_online_manual_action)
        self.help_menu.addAction(self.tab_info.open_offline_manual_action)
        self.help_menu.addAction(self.tab_info.fill_bug_report_action)
        self.help_menu.addAction(self.tab_info.authors_action)
        self.help_menu.addAction(self.tab_info.show_about_action)

        self.statusBar().setStyleSheet("QStatusBar{color:rgba(0,0,0,128);font-size: 8pt;}")
        self.status_bar_normal_style = self.statusBar().styleSheet()
        self.statusBar().showMessage("%s" % app_info.app_name, 2000)
        self.releaseInfo = QtWidgets.QLabel()
        self.statusBar().addPermanentWidget(self.releaseInfo)
        self.releaseInfo.setStyleSheet("QLabel{color:rgba(0,0,0,128);font-size: 8pt;}")
        timer = QtCore.QTimer(self)
        # noinspection PyUnresolvedReferences
        timer.timeout.connect(self.update_gui)
        timer.start(1500)
        self.timer_execs = 0

        self.data_cleared()
        self.tabs.blockSignals(False)

        logger.info("* > APP: initialized!")
Beispiel #4
0
class MainWin(QtWidgets.QMainWindow):

    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)

        logger.info("* > APP: initializing ...")

        # set the application name and the version
        self.name = app_info.app_name
        self.version = app_info.app_version
        self.setWindowTitle('%s v.%s' % (self.name, self.version))
        # noinspection PyArgumentList
        _app = QtCore.QCoreApplication.instance()
        _app.setApplicationName('%s' % self.name)
        _app.setOrganizationName("HydrOffice")
        _app.setOrganizationDomain("hydroffice.org")

        # set the minimum and the initial size
        self.setMinimumSize(640, 480)
        self.resize(920, 640)

        # set icons
        self.setWindowIcon(QtGui.QIcon(app_info.app_icon_path))

        # check if setup db exists; if yes, ask to copy
        has_setup = SoundSpeedLibrary.setup_exists()
        logger.info("setup exists: %s" % has_setup)
        if not has_setup:
            other_setups = SoundSpeedLibrary.list_other_setups()
            if len(other_setups) != 0:
                logger.debug("other existing setups: %d" % len(other_setups))
                # noinspection PyCallByClass
                sel, ok = QtWidgets.QInputDialog.getItem(self, 'Do you want to copy an existing setup?',
                                                         'Select one (or click on Cancel to create a new one):',
                                                         other_setups, 0, False)
                if ok:
                    SoundSpeedLibrary.copy_setup(input_setup=sel)

        # create the project
        self.lib = SoundSpeedLibrary(callbacks=QtCallbacks(parent=self), progress=QtProgress(parent=self))
        logger.info("current configuration:\n%s" % Helper(lib_info=lib_info).package_info())
        self.check_woa09()
        self.check_woa13()
        # self.check_rtofs()  # no need to wait for the download at the beginning
        self.check_sis4()
        self.check_sis5()
        self.check_sippican()
        self.check_mvp()

        # init default settings
        settings = QtCore.QSettings()
        export_folder = settings.value("export_folder")
        if (export_folder is None) or (not os.path.exists(export_folder)):
            settings.setValue("export_folder", self.lib.data_folder)
        import_folder = settings.value("import_folder")
        if (import_folder is None) or (not os.path.exists(import_folder)):
            settings.setValue("import_folder", self.lib.data_folder)

        # menu

        self.menu = self.menuBar()
        self.file_menu = self.menu.addMenu("File")
        self.edit_menu = self.menu.addMenu("Process")
        self.database_menu = self.menu.addMenu("Database")
        self.monitor_menu = self.menu.addMenu("Monitor")
        self.server_menu = self.menu.addMenu("Server")
        self.setup_menu = self.menu.addMenu("Setup")
        self.help_menu = self.menu.addMenu("Help")

        # make tabs
        self.tabs = QtWidgets.QTabWidget()
        self.setCentralWidget(self.tabs)
        self.tabs.setIconSize(QtCore.QSize(42, 42))
        self.tabs.blockSignals(True)  # during the initialization
        # noinspection PyUnresolvedReferences
        self.tabs.currentChanged.connect(self.on_change)  # changed!
        # editor
        self.tab_editor = Editor(lib=self.lib, main_win=self)
        self.idx_editor = self.tabs.insertTab(0, self.tab_editor,
                                              QtGui.QIcon(os.path.join(app_info.app_media_path, 'editor.png')), "")
        self.tabs.setTabToolTip(self.idx_editor, "Editor")
        # database
        self.tab_database = Database(lib=self.lib, main_win=self)
        self.idx_database = self.tabs.insertTab(1, self.tab_database,
                                                QtGui.QIcon(os.path.join(app_info.app_media_path, 'database.png')), "")
        self.tabs.setTabToolTip(self.idx_database, "Database")
        # survey data monitor
        self.has_sdm_support = True
        try:  # try.. except to make SSM working also without SDM
            # noinspection PyUnresolvedReferences
            from hyo2.surveydatamonitor.app.widgets.monitor import SurveyDataMonitor
            self.tab_monitor = SurveyDataMonitor(lib=self.lib, main_win=self)
            self.idx_monitor = self.tabs.insertTab(3, self.tab_monitor,
                                                   QtGui.QIcon(
                                                       os.path.join(app_info.app_media_path, 'surveydatamonitor.png')),
                                                   "")
            self.tabs.setTabToolTip(self.idx_monitor, "Survey Data Monitor")
            logger.info("Support for Survey Monitor: ON")
        except Exception as e:
            traceback.print_exc()
            self.has_sdm_support = False
            logger.info("Support for Survey Monitor: OFF(%s)" % e)
        # server
        self.tab_server = Server(lib=self.lib, main_win=self)
        self.idx_server = self.tabs.insertTab(4, self.tab_server,
                                              QtGui.QIcon(os.path.join(app_info.app_media_path, 'server.png')), "")
        self.tabs.setTabToolTip(self.idx_server, "Synthetic Profile Server")

        # refraction
        # self.tab_refraction = Refraction(lib=self.lib, main_win=self)
        # idx = self.tabs.insertTab(5, self.tab_refraction,
        #                           QtGui.QIcon(os.path.join(app_info.app_media_path, 'refraction.png')), "")
        # self.tabs.setTabToolTip(idx, "Refraction Monitor")
        # setup
        self.tab_setup = Settings(lib=self.lib, main_win=self)
        self.idx_setup = self.tabs.insertTab(6, self.tab_setup,
                                             QtGui.QIcon(os.path.join(app_info.app_media_path, 'settings.png')), "")
        self.tabs.setTabToolTip(self.idx_setup, "Setup")
        # info
        self.tab_info = InfoTab(main_win=self, lib_info=lib_info, app_info=app_info,
                                with_online_manual=True,
                                with_offline_manual=True,
                                with_bug_report=True,
                                with_hydroffice_link=True,
                                with_ccom_link=True,
                                with_noaa_link=True,
                                with_unh_link=True,
                                with_license=True)
        self.idx_info = self.tabs.insertTab(6, self.tab_info,
                                            QtGui.QIcon(os.path.join(app_info.app_media_path, 'info.png')), "")
        self.tabs.setTabToolTip(self.idx_info, "Info")
        # Help menu
        self.help_menu.addAction(self.tab_info.open_online_manual_action)
        self.help_menu.addAction(self.tab_info.open_offline_manual_action)
        self.help_menu.addAction(self.tab_info.fill_bug_report_action)
        self.help_menu.addAction(self.tab_info.authors_action)
        self.help_menu.addAction(self.tab_info.show_about_action)

        self.statusBar().setStyleSheet("QStatusBar{color:rgba(0,0,0,128);font-size: 8pt;}")
        self.status_bar_normal_style = self.statusBar().styleSheet()
        self.statusBar().showMessage("%s" % app_info.app_name, 2000)
        self.releaseInfo = QtWidgets.QLabel()
        self.statusBar().addPermanentWidget(self.releaseInfo)
        self.releaseInfo.setStyleSheet("QLabel{color:rgba(0,0,0,128);font-size: 8pt;}")
        timer = QtCore.QTimer(self)
        # noinspection PyUnresolvedReferences
        timer.timeout.connect(self.update_gui)
        timer.start(1500)
        self.timer_execs = 0

        self.data_cleared()
        self.tabs.blockSignals(False)

        logger.info("* > APP: initialized!")

    def on_change(self, i):
        # logger.debug("Current Tab Index: %s" % type(self.tabs.widget(i)))
        if type(self.tabs.widget(i)) == Settings:
            self.tab_setup.setup_changed()

    def switch_to_editor_tab(self):
        if self.tabs.currentIndex() != self.idx_editor:
            self.tabs.setCurrentIndex(self.idx_editor)

    def switch_to_database_tab(self):
        if self.tabs.currentIndex() != self.idx_database:
            self.tabs.setCurrentIndex(self.idx_database)

    def switch_to_monitor_tab(self):
        if self.tabs.currentIndex() != self.idx_monitor:
            self.tabs.setCurrentIndex(self.idx_monitor)

    def switch_to_server_tab(self):
        if self.tabs.currentIndex() != self.idx_server:
            self.tabs.setCurrentIndex(self.idx_server)

    def switch_to_setup_tab(self):
        if self.tabs.currentIndex() != self.idx_setup:
            self.tabs.setCurrentIndex(self.idx_setup)

    def switch_to_info_tab(self):
        if self.tabs.currentIndex() != self.idx_info:
            self.tabs.setCurrentIndex(self.idx_info)

    def check_woa09(self):
        """ helper function that looks after WOA09 database"""
        if not self.lib.use_woa09():
            logger.debug('WOA09: disabled by settings')
            return

        if self.lib.has_woa09():
            logger.debug('WOA09: enabled')
            return

        msg = 'The WOA09 atlas is required by some advanced application functions.\n\n' \
              'The data set (~120MB) can be retrieved from:\n' \
              '   ftp.ccom.unh.edu/fromccom/hydroffice/woa09.red.zip\n' \
              'then unzipped it into:\n' \
              '   %s\n\n' \
              'Do you want that I perform this operation for you?\n' \
              'Internet connection is required!\n' % self.lib.woa09_folder
        # noinspection PyCallByClass
        ret = QtWidgets.QMessageBox.information(self, "Sound Speed Manager - WOA09 Atlas", msg,
                                                QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.No)
        if ret == QtWidgets.QMessageBox.No:
            msg = 'You can also manually install it. The steps are:\n' \
                  ' - download the archive from (anonymous ftp):\n' \
                  '   ftp.ccom.unh.edu/fromccom/hydroffice/woa09.red.zip\n' \
                  ' - unzip the archive into:\n' \
                  '   %s\n' \
                  ' - restart Sound Speed Manager\n' % self.lib.woa09_folder
            # noinspection PyCallByClass
            QtWidgets.QMessageBox.information(self, "Sound Speed Manager - WOA09 Atlas", msg,
                                              QtWidgets.QMessageBox.Ok)
            logger.debug('WOA09: disabled')
            return

        success = self.lib.download_woa09()
        if not success:
            msg = 'Unable to retrieve the WOA09 atlas.\n\n ' \
                  'You may manually install it. The steps are:\n' \
                  ' - download the archive from (anonymous ftp):\n' \
                  '   ftp.ccom.unh.edu/fromccom/hyo/woa09.red.zip\n' \
                  ' - unzip the archive into:\n' \
                  '   %s\n' \
                  ' - restart Sound Speed Manager\n' % self.lib.woa09_folder
            # noinspection PyCallByClass
            QtWidgets.QMessageBox.warning(self, "Sound Speed Manager - WOA09 Atlas", msg,
                                          QtWidgets.QMessageBox.Ok)
            logger.debug('WOA09: disabled')
            return

        logger.debug('WOA09: enabled')

    def check_woa13(self):
        """ helper function that looks after WOA13 database"""
        if not self.lib.use_woa13():
            logger.debug('WOA13: disabled by settings')
            return

        if self.lib.has_woa13():
            logger.debug('WOA13: enabled')
            return

        msg = 'The WOA13 atlas is required by some advanced application functions.\n\n' \
              'The data set (~4GB) can be retrieved from:\n' \
              '   ftp.ccom.unh.edu/fromccom/hydroffice/woa13_temp.red.zip\n' \
              '   ftp.ccom.unh.edu/fromccom/hydroffice/woa13_sal.red.zip\n' \
              'then unzipped it into:\n' \
              '   %s\n\n' \
              'Do you want that I perform this operation for you?\n' \
              'Internet connection is required!\n' % self.lib.woa13_folder
        # noinspection PyCallByClass
        ret = QtWidgets.QMessageBox.information(self, "Sound Speed Manager - WOA13 Atlas", msg,
                                                QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.No)
        if ret == QtWidgets.QMessageBox.No:
            msg = 'You can also manually install it. The steps are:\n' \
                  ' - download the archive from (anonymous ftp):\n' \
                  '   ftp.ccom.unh.edu/fromccom/hydroffice/woa13_temp.red.zip\n' \
                  '   ftp.ccom.unh.edu/fromccom/hydroffice/woa13_sal.red.zip\n' \
                  ' - unzip the archive into:\n' \
                  '   %s\n' \
                  ' - restart Sound Speed Manager\n' % self.lib.woa13_folder
            # noinspection PyCallByClass
            QtWidgets.QMessageBox.information(self, "Sound Speed Manager - WOA13 Atlas", msg,
                                              QtWidgets.QMessageBox.Ok)
            logger.debug('WOA13: disabled')
            return

        success = self.lib.download_woa13()
        if not success:
            msg = 'Unable to retrieve the WOA13 atlas.\n\n ' \
                  'You may manually install it. The steps are:\n' \
                  ' - download the archive from (anonymous ftp):\n' \
                  '   ftp.ccom.unh.edu/fromccom/hyo/woa13_temp.red.zip\n' \
                  '   ftp.ccom.unh.edu/fromccom/hyo/woa13_sal.red.zip\n' \
                  ' - unzip the archive into:\n' \
                  '   %s\n' \
                  ' - restart Sound Speed Manager\n' % self.lib.woa13_folder
            # noinspection PyCallByClass
            QtWidgets.QMessageBox.warning(self, "Sound Speed Manager - WOA13 Atlas", msg,
                                          QtWidgets.QMessageBox.Ok)
            logger.debug('WOA13: disabled')
            return

        logger.debug('WOA13: enabled')

    def check_rtofs(self):
        """ helper function that looks after RTOFS connection"""
        if not self.lib.use_rtofs():
            logger.debug('RTOFS: disabled by settings')
            return

        if self.lib.has_rtofs():
            logger.debug('RTOFS: enabled')
            return

        success = self.lib.download_rtofs()
        if not success:
            msg = 'Unable to retrieve the RTOFS atlas.\n\n ' \
                  'The application needs an internet connection to access\n' \
                  'this server (with port 9090 open):\n' \
                  ' - http://nomads.ncep.noaa.gov:9090\n\n' \
                  'You can disable the RTOFS support in Settings/Basic/Use RTOFS.\n'
            # noinspection PyCallByClass
            QtWidgets.QMessageBox.warning(self, "Sound Speed Manager - RTOFS Atlas", msg,
                                          QtWidgets.QMessageBox.Ok)
            logger.debug('RTOFS: disabled')
            return

        logger.debug('RTOFS: enabled')

    def check_sis4(self):
        if self.lib.use_sis4():
            if not self.lib.listen_sis4():
                msg = 'Unable to listen SIS4.'
                # noinspection PyCallByClass
                QtWidgets.QMessageBox.warning(self, "Sound Speed Manager - SIS4", msg,
                                              QtWidgets.QMessageBox.Ok)
        else:
            if not self.lib.stop_listen_sis4():
                msg = 'Unable to stop listening SIS.'
                # noinspection PyCallByClass
                QtWidgets.QMessageBox.warning(self, "Sound Speed Manager - SIS4", msg,
                                              QtWidgets.QMessageBox.Ok)

    def check_sis5(self):
        if self.lib.use_sis5():
            if not self.lib.listen_sis5():
                msg = 'Unable to listen SIS5.'
                # noinspection PyCallByClass
                QtWidgets.QMessageBox.warning(self, "Sound Speed Manager - SIS5", msg,
                                              QtWidgets.QMessageBox.Ok)
        else:
            if not self.lib.stop_listen_sis5():
                msg = 'Unable to stop listening SIS5.'
                # noinspection PyCallByClass
                QtWidgets.QMessageBox.warning(self, "Sound Speed Manager - SIS5", msg,
                                              QtWidgets.QMessageBox.Ok)

    def check_sippican(self):
        if self.lib.use_sippican():
            if not self.lib.listen_sippican():
                msg = 'Unable to listening Sippican.'
                # noinspection PyCallByClass
                QtWidgets.QMessageBox.warning(self, "Sound Speed Manager - Sippican", msg,
                                              QtWidgets.QMessageBox.Ok)
        else:
            if not self.lib.stop_listen_sippican():
                msg = 'Unable to stop listening Sippican.'
                # noinspection PyCallByClass
                QtWidgets.QMessageBox.warning(self, "Sound Speed Manager - Sippican", msg,
                                              QtWidgets.QMessageBox.Ok)

    def check_mvp(self):
        if self.lib.use_mvp():
            if not self.lib.listen_mvp():
                msg = 'Unable to listening MVP.'
                # noinspection PyCallByClass
                QtWidgets.QMessageBox.warning(self, "Sound Speed Manager - MVP", msg,
                                              QtWidgets.QMessageBox.Ok)
        else:
            if not self.lib.stop_listen_mvp():
                msg = 'Unable to stop listening MVP.'
                # noinspection PyCallByClass
                QtWidgets.QMessageBox.warning(self, "Sound Speed Manager - MVP", msg,
                                              QtWidgets.QMessageBox.Ok)

    def data_cleared(self):
        self.tab_editor.data_cleared()
        self.tab_database.data_cleared()
        self.tab_server.data_cleared()
        # self.tab_refraction.data_cleared()
        self.tab_setup.data_cleared()

    def data_imported(self):
        self.tab_editor.data_imported()
        self.tab_database.data_imported()
        self.tab_server.data_imported()
        # self.tab_refraction.data_imported()
        self.tab_setup.data_imported()

    def data_stored(self):
        self.tab_editor.data_stored()
        self.tab_database.data_stored()
        self.tab_server.data_stored()
        # self.tab_refraction.data_stored()
        self.tab_setup.data_stored()

    def data_removed(self):
        self.tab_editor.data_removed()
        self.tab_database.data_removed()
        self.tab_server.data_removed()
        # self.tab_refraction.data_removed()
        self.tab_setup.data_removed()

    def server_started(self):
        # clear widgets as for data clear
        self.data_cleared()

        self.tab_editor.server_started()
        self.tab_database.server_started()
        self.tab_server.server_started()
        # self.tab_refraction.server_started()
        self.tab_setup.server_started()
        self.statusBar().setStyleSheet("QStatusBar{color:rgba(0,0,0,128);"
                                       "font-size: 8pt;background-color:rgba(51,204,255,128);}")

    def server_stopped(self):
        self.tab_editor.server_stopped()
        self.tab_database.server_stopped()
        self.tab_server.server_stopped()
        # self.tab_refraction.server_stopped()
        self.tab_setup.server_stopped()
        self.statusBar().setStyleSheet(self.status_bar_normal_style)

    def _check_latest_release(self):

        new_release = False
        new_bugfix = False
        latest_version = None
        try:
            response = urlopen('http://www.hydroffice.org/latest/soundspeedmanager.txt', timeout=2)
            latest_version = response.read().split()[0].decode()

            cur_maj, cur_min, cur_fix = app_info.app_version.split('.')
            lat_maj, lat_min, lat_fix = latest_version.split('.')

            if int(lat_maj) > int(cur_maj):
                new_release = True

            elif (int(lat_maj) == int(cur_maj)) and (int(lat_min) > int(cur_min)):
                new_release = True

            elif (int(lat_maj) == int(cur_maj)) and (int(lat_min) == int(cur_min)) and (int(lat_fix) > int(cur_fix)):
                new_bugfix = True

        except (URLError, ssl.SSLError, socket.timeout, ConnectionResetError, ValueError) as e:
            logger.info("unable to check latest release (reason: %s)" % e)

        if new_release:
            logger.info("new release available: %s" % latest_version)
            self.releaseInfo.setText("New release available: %s" % latest_version)
            self.releaseInfo.setStyleSheet("QLabel{background-color:rgba(255,0,0,128);"
                                           "color:rgba(0,0,0,128);"
                                           "font-size: 8pt;}")

        elif new_bugfix:
            logger.info("new bugfix available: %s" % latest_version)
            self.releaseInfo.setText("New bugfix available: %s" % latest_version)
            self.releaseInfo.setStyleSheet("QLabel{background-color:rgba(255,255,0,128);"
                                           "color:rgba(0,0,0,128);"
                                           "font-size: 8pt;}")

    def update_gui(self):

        if self.timer_execs % 200 == 0:
            # logger.debug("timer executions: %d" % self.timer_execs)
            self._check_latest_release()

        self.timer_execs += 1

        # if self.lib.setup.noaa_tools:
        #     self.tab_seacat.setEnabled(True)
        # else:
        #     self.tab_seacat.setDisabled(True)

        # update the windows title
        self.setWindowTitle('%s v.%s [project: %s]' % (self.name, self.version, self.lib.current_project))

        msg = str()

        tokens = list()
        if self.lib.server.is_alive():
            tokens.append("SRV")
        if self.lib.has_ref():
            tokens.append("REF")
        if self.lib.use_rtofs():
            tokens.append("RTF")
        if self.lib.use_gomofs():
            tokens.append("GoM")
        if self.lib.use_woa09():
            tokens.append("W09")
        if self.lib.use_woa13():
            tokens.append("W13")
        if self.lib.use_sippican():
            tokens.append("SIP")
        if self.lib.use_mvp():
            tokens.append("MVP")
        if self.lib.use_sis4():
            tokens.append("SIS4")
        if self.lib.use_sis5():
            tokens.append("SIS5")
        msg += "|".join(tokens)

        if (not self.lib.use_sis4()) and (not self.lib.use_sis5()):  # in case that SIS was disabled
            self.statusBar().showMessage(msg, 1000)
            return

        msg += "  -  "  # add some spacing

        if self.lib.use_sis4():

            if self.lib.listeners.sis4.nav is not None:
                # time stamp
                msg += "time:"
                if self.lib.listeners.sis4.nav.dg_time is not None:
                    msg += "%s, " % (self.lib.listeners.sis4.nav.dg_time.strftime("%H:%M:%S"))

                else:
                    msg += "NA, "

                # position
                msg += "pos:"
                if (self.lib.listeners.sis4.nav.latitude is not None) and \
                        (self.lib.listeners.sis4.nav.longitude is not None):

                    latitude = self.lib.listeners.sis4.nav.latitude
                    if latitude >= 0:
                        letter = "N"
                    else:
                        letter = "S"
                    lat_min = float(60 * math.fabs(latitude - int(latitude)))
                    lat_str = "%02d\N{DEGREE SIGN}%7.3f'%s" % (int(math.fabs(latitude)), lat_min, letter)

                    longitude = self.lib.listeners.sis4.nav.longitude
                    if longitude < 0:
                        letter = "W"
                    else:
                        letter = "E"
                    lon_min = float(60 * math.fabs(longitude - int(longitude)))
                    lon_str = "%03d\N{DEGREE SIGN}%7.3f'%s" % (int(math.fabs(longitude)), lon_min, letter)

                    msg += "(%s, %s),  " % (lat_str, lon_str)

                else:
                    msg += "(NA, NA),  "

            if self.lib.listeners.sis4.xyz88 is not None:
                msg += 'tss:'
                if self.lib.listeners.sis4.xyz88.sound_speed is not None:
                    msg += '%.1f m/s,  ' % self.lib.listeners.sis4.xyz88.sound_speed

                else:
                    msg += 'NA m/s,  '

                msg += 'avg.depth:'
                mean_depth = self.lib.listeners.sis4.xyz88.mean_depth
                if mean_depth:
                    msg += '%.1f m' % mean_depth
                else:
                    msg += 'NA m'

            else:
                msg += 'XYZ88 NA [pinging?]'

        if self.lib.use_sis5():

            if self.lib.listeners.sis5.spo is not None:
                # time stamp
                msg += "time:"
                if self.lib.listeners.sis5.spo.dg_time is not None:
                    msg += "%s, " % (self.lib.listeners.sis5.spo.dg_time.strftime("%H:%M:%S"))

                else:
                    msg += "NA, "

                # position
                msg += "pos:"
                if (self.lib.listeners.sis5.spo.latitude is not None) and \
                        (self.lib.listeners.sis5.spo.longitude is not None):

                    latitude = self.lib.listeners.sis5.spo.latitude
                    if latitude >= 0:
                        letter = "N"
                    else:
                        letter = "S"
                    lat_min = float(60 * math.fabs(latitude - int(latitude)))
                    lat_str = "%02d\N{DEGREE SIGN}%7.3f'%s" % (int(math.fabs(latitude)), lat_min, letter)

                    longitude = self.lib.listeners.sis5.spo.longitude
                    if longitude < 0:
                        letter = "W"
                    else:
                        letter = "E"
                    lon_min = float(60 * math.fabs(longitude - int(longitude)))
                    lon_str = "%03d\N{DEGREE SIGN}%7.3f'%s" % (int(math.fabs(longitude)), lon_min, letter)

                    msg += "(%s, %s),  " % (lat_str, lon_str)

                else:
                    msg += "(NA, NA),  "

            if self.lib.listeners.sis5.mrz is not None:
                msg += 'tss:'
                if self.lib.listeners.sis5.mrz.tss is not None:
                    msg += '%.1f m/s,  ' % self.lib.listeners.sis5.mrz.tss

                else:
                    msg += 'NA m/s,  '

                msg += 'avg.depth:'
                mean_depth = self.lib.listeners.sis5.mrz.mean_depth
                if mean_depth:
                    msg += '%.1f m' % mean_depth
                else:
                    msg += 'NA m'

            else:
                msg += 'MRZ NA [pinging?]'

        self.statusBar().showMessage(msg, 2000)
        if self.lib.has_ssp():

            if self.lib.server.is_alive():  # server mode
                if not self.tab_server.dataplots.is_drawn:
                    self.tab_server.dataplots.reset()
                    self.tab_server.dataplots.on_first_draw()

                self.tab_server.dataplots.update_data()
                self.tab_server.dataplots.redraw()

            else:  # user mode
                if self.lib.has_mvp_to_process() or self.lib.has_sippican_to_process():
                    # logger.debug("data to import from listeners")
                    # logger.debug("plot drawn: %s" % self.tab_editor.dataplots.is_drawn)
                    if not self.tab_editor.dataplots.is_drawn:
                        self.data_imported()

                    if self.lib.cur.listener_completed and not self.lib.cur.listener_displayed:
                        self.tab_editor.dataplots.on_first_draw()
                        self.lib.cur.listener_displayed = True

                self.tab_editor.dataplots.update_data()
                self.tab_editor.dataplots.redraw()

        if not self.lib.server.is_alive():  # user mode - listeners
            if self.lib.has_mvp_to_process() or self.lib.has_sippican_to_process():
                self.statusBar().setStyleSheet("QStatusBar{color:rgba(0,0,0,128);"
                                               "font-size: 8pt;background-color:rgba(255,163,102,128);}")
            else:
                self.statusBar().setStyleSheet(self.status_bar_normal_style)

    def change_info_url(self, url):
        self.tab_info.change_url(url)

    def exception_hook(self, ex_type: type, ex_value: BaseException, tb: traceback) -> None:
        sys.__excepthook__(ex_type, ex_value, tb)

        # first manage case of not being an exception (e.g., keyboard interrupts)
        if not issubclass(ex_type, Exception):
            msg = str(ex_value)
            if not msg:
                msg = ex_value.__class__.__name__
            logger.info(msg)
            self.close()
            return

        dlg = ExceptionDialog(app_info=app_info, lib_info=lib_info, ex_type=ex_type, ex_value=ex_value, tb=tb)
        ret = dlg.exec_()
        if ret == QtWidgets.QDialog.Rejected:
            if not dlg.user_triggered:
                self.close()
        else:
            logger.warning("ignored exception")

    # Quitting #

    def _do_you_really_want(self, title="Quit", text="quit"):
        """helper function that show to the user a message windows asking to confirm an action"""
        msg_box = QtWidgets.QMessageBox(self)
        msg_box.setWindowTitle(title)
        msg_box.setIconPixmap(QtGui.QPixmap(app_info.app_icon_path).scaled(QtCore.QSize(36, 36)))
        msg_box.setText('Do you really want to %s?' % text)
        msg_box.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
        msg_box.setDefaultButton(QtWidgets.QMessageBox.No)
        return msg_box.exec_()

    def closeEvent(self, event):
        """ actions to be done before close the app """
        reply = self._do_you_really_want("Quit", "quit %s" % app_info.app_name)
        # reply = QtWidgets.QMessageBox.Yes
        if reply == QtWidgets.QMessageBox.Yes:
            event.accept()
            self.lib.close()
            if self.has_sdm_support:
                self.tab_monitor.stop_plotting()
            super(MainWin, self).closeEvent(event)
        else:
            event.ignore()

    # -------------------------- development-only --------------------------

    def do(self):
        """ development-mode only helper function """
        pass
Beispiel #5
0
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)

        logger.info("current configuration:\n%s" %
                    Helper(lib_info=lib_info).package_info())

        # set the application name
        self.name = app_info.app_name
        self.version = app_info.app_version
        self.setWindowTitle('%s v.%s' % (self.name, self.version))
        self.setMinimumSize(QtCore.QSize(500, 500))
        self.resize(QtCore.QSize(920, 840))

        # noinspection PyArgumentList
        _app = QtCore.QCoreApplication.instance()
        _app.setApplicationName('%s' % self.name)
        _app.setOrganizationName("HydrOffice")
        _app.setOrganizationDomain("hydroffice.org")

        # set icons
        icon_info = QtCore.QFileInfo(app_info.app_icon_path)
        self.setWindowIcon(QtGui.QIcon(icon_info.absoluteFilePath()))
        if Helper.is_windows():

            try:
                # This is needed to display the app icon on the taskbar on Windows 7
                import ctypes
                app_id = '%s v.%s' % (self.name, self.version)
                ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(
                    app_id)

            except AttributeError as e:
                logger.debug("Unable to change app icon: %s" % e)

        # make tabs
        self.tabs = QtWidgets.QTabWidget()
        self.setCentralWidget(self.tabs)
        self.tabs.setIconSize(QtCore.QSize(52, 52))
        # qaqc tab
        self.tab_qax = QAXWidget(main_win=self)
        # noinspection PyArgumentList
        idx = self.tabs.insertTab(0, self.tab_qax,
                                  QtGui.QIcon(app_info.app_icon_path), "")
        self.tabs.setTabToolTip(idx, "QAX")
        # info
        self.tab_info = InfoTab(lib_info=lib_info,
                                app_info=app_info,
                                with_online_manual=True,
                                with_offline_manual=True,
                                with_bug_report=True,
                                with_hydroffice_link=True,
                                with_ccom_link=True,
                                with_noaa_link=True,
                                with_unh_link=False,
                                with_license=True,
                                with_noaa_57=True,
                                with_ausseabed_link=True,
                                main_win=self)
        # noinspection PyArgumentList
        idx = self.tabs.insertTab(
            1, self.tab_info, QtGui.QIcon(os.path.join(self.media,
                                                       'info.png')), "")
        self.tabs.setTabToolTip(idx, "Info")

        # init default settings
        settings = QtCore.QSettings()
        start_tab = settings.value("start_tab")
        if (start_tab is None) or (start_tab > 0):
            start_tab = 0
            settings.setValue("start_tab", start_tab)
        self.tabs.setCurrentIndex(start_tab)

        self.statusBar().setStyleSheet(
            "QStatusBar{color:rgba(0,0,0,128);font-size: 8pt;}")
        self.status_bar_normal_style = self.statusBar().styleSheet()
        self.statusBar().showMessage("%s" % app_info.app_version, 2000)
        timer = QtCore.QTimer(self)
        # noinspection PyUnresolvedReferences
        timer.timeout.connect(self.update_gui)
        # noinspection PyArgumentList
        timer.start(300000)  # 5 mins
        self.update_gui()
Beispiel #6
0
class MainWin(QtWidgets.QMainWindow):

    here = os.path.abspath(os.path.dirname(__file__))
    media = os.path.join(here, "media")

    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)

        logger.info("current configuration:\n%s" %
                    Helper(lib_info=lib_info).package_info())

        # set the application name
        self.name = app_info.app_name
        self.version = app_info.app_version
        self.setWindowTitle('%s v.%s' % (self.name, self.version))
        self.setMinimumSize(QtCore.QSize(500, 500))
        self.resize(QtCore.QSize(920, 840))

        # noinspection PyArgumentList
        _app = QtCore.QCoreApplication.instance()
        _app.setApplicationName('%s' % self.name)
        _app.setOrganizationName("HydrOffice")
        _app.setOrganizationDomain("hydroffice.org")

        # set icons
        icon_info = QtCore.QFileInfo(app_info.app_icon_path)
        self.setWindowIcon(QtGui.QIcon(icon_info.absoluteFilePath()))
        if Helper.is_windows():

            try:
                # This is needed to display the app icon on the taskbar on Windows 7
                import ctypes
                app_id = '%s v.%s' % (self.name, self.version)
                ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(
                    app_id)

            except AttributeError as e:
                logger.debug("Unable to change app icon: %s" % e)

        # make tabs
        self.tabs = QtWidgets.QTabWidget()
        self.setCentralWidget(self.tabs)
        self.tabs.setIconSize(QtCore.QSize(52, 52))
        # qaqc tab
        self.tab_qax = QAXWidget(main_win=self)
        # noinspection PyArgumentList
        idx = self.tabs.insertTab(0, self.tab_qax,
                                  QtGui.QIcon(app_info.app_icon_path), "")
        self.tabs.setTabToolTip(idx, "QAX")
        # info
        self.tab_info = InfoTab(lib_info=lib_info,
                                app_info=app_info,
                                with_online_manual=True,
                                with_offline_manual=True,
                                with_bug_report=True,
                                with_hydroffice_link=True,
                                with_ccom_link=True,
                                with_noaa_link=True,
                                with_unh_link=False,
                                with_license=True,
                                with_noaa_57=True,
                                with_ausseabed_link=True,
                                main_win=self)
        # noinspection PyArgumentList
        idx = self.tabs.insertTab(
            1, self.tab_info, QtGui.QIcon(os.path.join(self.media,
                                                       'info.png')), "")
        self.tabs.setTabToolTip(idx, "Info")

        # init default settings
        settings = QtCore.QSettings()
        start_tab = settings.value("start_tab")
        if (start_tab is None) or (start_tab > 0):
            start_tab = 0
            settings.setValue("start_tab", start_tab)
        self.tabs.setCurrentIndex(start_tab)

        self.statusBar().setStyleSheet(
            "QStatusBar{color:rgba(0,0,0,128);font-size: 8pt;}")
        self.status_bar_normal_style = self.statusBar().styleSheet()
        self.statusBar().showMessage("%s" % app_info.app_version, 2000)
        timer = QtCore.QTimer(self)
        # noinspection PyUnresolvedReferences
        timer.timeout.connect(self.update_gui)
        # noinspection PyArgumentList
        timer.start(300000)  # 5 mins
        self.update_gui()

    def update_gui(self):
        msg = str()
        tokens = list()

        new_release = False
        new_bugfix = False
        latest_version = None
        try:
            response = urlopen(app_info.app_latest_url, timeout=1)
            latest_version = response.read().split()[0].decode()

            cur_maj, cur_min, cur_fix = app_info.app_version.split('.')
            lat_maj, lat_min, lat_fix = latest_version.split('.')

            if int(lat_maj) > int(cur_maj):
                new_release = True

            elif (int(lat_maj)
                  == int(cur_maj)) and (int(lat_min) > int(cur_min)):
                new_release = True

            elif (int(lat_maj)
                  == int(cur_maj)) and (int(lat_min) == int(cur_min)) and (
                      int(lat_fix) > int(cur_fix)):
                new_bugfix = True

        except (URLError, ssl.SSLError, socket.timeout) as e:
            logger.info("unable to check latest release: %s" % e)

        except ValueError as e:
            logger.info("unable to parse version: %s" % e)

        if new_release:
            logger.info("new release available: %s" % latest_version)
            tokens.append("New release available: %s" % latest_version)
            self.statusBar().setStyleSheet(
                "QStatusBar{background-color:rgba(255,0,0,128);font-size: 8pt;}"
            )

        elif new_bugfix:
            logger.info("new bugfix available: %s" % latest_version)
            tokens.append("New bugfix available: %s" % latest_version)
            self.statusBar().setStyleSheet(
                "QStatusBar{background-color:rgba(255,255,0,128);font-size: 8pt;}"
            )

        else:
            self.statusBar().setStyleSheet(self.status_bar_normal_style)

        msg += "|".join(tokens)

        self.statusBar().showMessage(msg, 3000000)

    def change_info_url(self, url):
        self.tab_info.change_url(url)

    def exception_hook(self, ex_type: type, ex_value: BaseException,
                       tb: traceback) -> None:
        sys.__excepthook__(ex_type, ex_value, tb)

        # first manage case of not being an exception (e.g., keyboard interrupts)
        if not issubclass(ex_type, Exception):
            msg = str(ex_value)
            if not msg:
                msg = ex_value.__class__.__name__
            logger.info(msg)
            self.close()
            return

        dlg = ExceptionDialog(app_info=app_info,
                              lib_info=lib_info,
                              ex_type=ex_type,
                              ex_value=ex_value,
                              tb=tb)
        ret = dlg.exec_()
        if ret == QtWidgets.QDialog.Rejected:
            if not dlg.user_triggered:
                self.close()
        else:
            logger.warning("ignored exception")

    # Quitting #

    def do_you_really_want(self, title="Quit", text="quit"):
        msg_box = QtWidgets.QMessageBox(self)
        msg_box.setWindowTitle(title)
        msg_box.setIconPixmap(
            QtGui.QPixmap(app_info.app_icon_path).scaled(QtCore.QSize(60, 60)))
        msg_box.setText('Do you really want to %s?' % text)
        msg_box.setStandardButtons(QtWidgets.QMessageBox.Yes
                                   | QtWidgets.QMessageBox.No)
        msg_box.setDefaultButton(QtWidgets.QMessageBox.No)
        return msg_box.exec_()

    def closeEvent(self, event):
        """ actions to be done before close the app """
        reply = self.do_you_really_want("Quit", "quit %s" % self.name)

        if reply == QtWidgets.QMessageBox.Yes:

            # store current tab
            settings = QtCore.QSettings()
            settings.setValue("start_tab", self.tabs.currentIndex())

            event.accept()
            super().closeEvent(event)

        else:

            event.ignore()

    def do(self):
        logger.warning("DEV MODE")
        from hyo2.qax.lib.qa_json import QAJson
        self.tab_qax.tab_inputs._add_json(QAJson.example_paths()[-1])
        self.tab_qax.change_tabs(self.tab_qax.idx_qc_tools)
        self.tab_qax.tab_qc_tools.display_json()
    def __init__(self, parent=None, standalone=False):
        super().__init__(parent)
        self.standalone = standalone
        self.ask_quit = True
        self.settings = QtCore.QSettings()
        self.setObjectName(app_info.app_main_window_object_name)

        # set the application name and icon
        title = '%s v.%s' % (app_info.app_name, app_info.app_version)
        if self.is_beta:
            title += " BETA"
        self.setWindowTitle(title)
        self.setWindowIcon(QtGui.QIcon(app_info.app_icon_path))

        # set the size
        self.setMinimumSize(QtCore.QSize(300, 200))
        self.resize(QtCore.QSize(800, 600))
        self.setContentsMargins(0, 0, 0, 0)

        # set status bar
        self.statusBar()
        self.status_bar_normal_style = self.statusBar().styleSheet()
        self.statusBar().showMessage("%s" % app_info.app_version, 2000)

        # create menu
        self.menu_root = self.menuBar()
        if self.standalone:
            self.menu_file = self.menu_root.addMenu("File")
        self.menu_setup = self.menu_root.addMenu("Setup")
        self.menu_help = self.menu_root.addMenu("Help")
        self.menu_setup_layout = None

        # add main frame and layout
        self.frame = QtWidgets.QFrame(parent=self)
        self.setCentralWidget(self.frame)
        self.frame_layout = QtWidgets.QVBoxLayout()
        self.frame.setLayout(self.frame_layout)

        # make tabs
        self.tabs = QtWidgets.QTabWidget()
        # tabs icon sizes
        self.set_tabs_icon_size(
            int(
                self.settings.value("tabs/icon_size",
                                    app_info.app_tabs_icon_size)))
        # - Arch
        self.tab_arch = ArchTab(main_win=self)
        # noinspection PyArgumentList
        self.tab_arch_idx = self.tabs.insertTab(
            0, self.tab_arch,
            QtGui.QIcon(os.path.join(app_info.app_media_path, "tab_arch.png")),
            "")
        self.tabs.setTabToolTip(self.tab_arch_idx, "Arch")
        # - Arch Compare
        self.tab_compare = ArchTabCompare(main_win=self)
        # noinspection PyArgumentList
        self.tab_compare_idx = self.tabs.insertTab(
            1, self.tab_compare,
            QtGui.QIcon(
                os.path.join(app_info.app_media_path, "tab_arch_compare.png")),
            "")
        self.tabs.setTabToolTip(self.tab_compare_idx, "Arch Compare")
        # - Arch 3D
        self.tab_arch3d = ArchTab3D(main_win=self)
        # noinspection PyArgumentList
        self.tab_arch3d_idx = self.tabs.insertTab(
            2, self.tab_arch3d,
            QtGui.QIcon(
                os.path.join(app_info.app_media_path, "tab_arch_3d.png")), "")
        self.tabs.setTabToolTip(self.tab_arch3d_idx, "Arch 3D")
        # - info
        if self.standalone:
            self.tab_info = InfoTab(main_win=self,
                                    lib_info=lib_info,
                                    app_info=app_info,
                                    with_online_manual=True,
                                    with_offline_manual=True,
                                    with_bug_report=True,
                                    with_hydroffice_link=True,
                                    with_ccom_link=True,
                                    with_noaa_link=True,
                                    with_unh_link=True,
                                    with_license=True)
            # noinspection PyArgumentList
            self.tab_info_idx = self.tabs.insertTab(
                3, self.tab_info,
                QtGui.QIcon(
                    os.path.join(app_info.app_media_path, "tab_info.png")), "")
            self.tabs.setTabToolTip(self.tab_info_idx, "Info")
        # noinspection PyUnresolvedReferences
        self.tabs.currentChanged.connect(self._on_tab_changed)
        # add tabs
        self.frame_layout.addWidget(self.tabs)

        # toolbars icon sizes
        self.set_toolbars_icon_size(
            int(
                self.settings.value("toolbars/icon_size",
                                    app_info.app_toolbars_icon_size)))

        # finalize menus
        self.add_menus()

        # save default state and restore last state
        self.settings.setValue("main_window/geometry_default",
                               self.saveGeometry())
        self.settings.setValue("main_window/state_default", self.saveState())
        self.restoreGeometry(self.settings.value("main_window/geometry"))
        self.restoreState(self.settings.value("main_window/state"))

        # periodical checks
        timer = QtCore.QTimer(self)
        # noinspection PyUnresolvedReferences
        timer.timeout.connect(self.update_status)
        # noinspection PyArgumentList
        timer.start(300000)  # each 5 minutes
        self.update_status()
class ArchWindow(QtWidgets.QMainWindow):

    is_beta = True

    def __init__(self, parent=None, standalone=False):
        super().__init__(parent)
        self.standalone = standalone
        self.ask_quit = True
        self.settings = QtCore.QSettings()
        self.setObjectName(app_info.app_main_window_object_name)

        # set the application name and icon
        title = '%s v.%s' % (app_info.app_name, app_info.app_version)
        if self.is_beta:
            title += " BETA"
        self.setWindowTitle(title)
        self.setWindowIcon(QtGui.QIcon(app_info.app_icon_path))

        # set the size
        self.setMinimumSize(QtCore.QSize(300, 200))
        self.resize(QtCore.QSize(800, 600))
        self.setContentsMargins(0, 0, 0, 0)

        # set status bar
        self.statusBar()
        self.status_bar_normal_style = self.statusBar().styleSheet()
        self.statusBar().showMessage("%s" % app_info.app_version, 2000)

        # create menu
        self.menu_root = self.menuBar()
        if self.standalone:
            self.menu_file = self.menu_root.addMenu("File")
        self.menu_setup = self.menu_root.addMenu("Setup")
        self.menu_help = self.menu_root.addMenu("Help")
        self.menu_setup_layout = None

        # add main frame and layout
        self.frame = QtWidgets.QFrame(parent=self)
        self.setCentralWidget(self.frame)
        self.frame_layout = QtWidgets.QVBoxLayout()
        self.frame.setLayout(self.frame_layout)

        # make tabs
        self.tabs = QtWidgets.QTabWidget()
        # tabs icon sizes
        self.set_tabs_icon_size(
            int(
                self.settings.value("tabs/icon_size",
                                    app_info.app_tabs_icon_size)))
        # - Arch
        self.tab_arch = ArchTab(main_win=self)
        # noinspection PyArgumentList
        self.tab_arch_idx = self.tabs.insertTab(
            0, self.tab_arch,
            QtGui.QIcon(os.path.join(app_info.app_media_path, "tab_arch.png")),
            "")
        self.tabs.setTabToolTip(self.tab_arch_idx, "Arch")
        # - Arch Compare
        self.tab_compare = ArchTabCompare(main_win=self)
        # noinspection PyArgumentList
        self.tab_compare_idx = self.tabs.insertTab(
            1, self.tab_compare,
            QtGui.QIcon(
                os.path.join(app_info.app_media_path, "tab_arch_compare.png")),
            "")
        self.tabs.setTabToolTip(self.tab_compare_idx, "Arch Compare")
        # - Arch 3D
        self.tab_arch3d = ArchTab3D(main_win=self)
        # noinspection PyArgumentList
        self.tab_arch3d_idx = self.tabs.insertTab(
            2, self.tab_arch3d,
            QtGui.QIcon(
                os.path.join(app_info.app_media_path, "tab_arch_3d.png")), "")
        self.tabs.setTabToolTip(self.tab_arch3d_idx, "Arch 3D")
        # - info
        if self.standalone:
            self.tab_info = InfoTab(main_win=self,
                                    lib_info=lib_info,
                                    app_info=app_info,
                                    with_online_manual=True,
                                    with_offline_manual=True,
                                    with_bug_report=True,
                                    with_hydroffice_link=True,
                                    with_ccom_link=True,
                                    with_noaa_link=True,
                                    with_unh_link=True,
                                    with_license=True)
            # noinspection PyArgumentList
            self.tab_info_idx = self.tabs.insertTab(
                3, self.tab_info,
                QtGui.QIcon(
                    os.path.join(app_info.app_media_path, "tab_info.png")), "")
            self.tabs.setTabToolTip(self.tab_info_idx, "Info")
        # noinspection PyUnresolvedReferences
        self.tabs.currentChanged.connect(self._on_tab_changed)
        # add tabs
        self.frame_layout.addWidget(self.tabs)

        # toolbars icon sizes
        self.set_toolbars_icon_size(
            int(
                self.settings.value("toolbars/icon_size",
                                    app_info.app_toolbars_icon_size)))

        # finalize menus
        self.add_menus()

        # save default state and restore last state
        self.settings.setValue("main_window/geometry_default",
                               self.saveGeometry())
        self.settings.setValue("main_window/state_default", self.saveState())
        self.restoreGeometry(self.settings.value("main_window/geometry"))
        self.restoreState(self.settings.value("main_window/state"))

        # periodical checks
        timer = QtCore.QTimer(self)
        # noinspection PyUnresolvedReferences
        timer.timeout.connect(self.update_status)
        # noinspection PyArgumentList
        timer.start(300000)  # each 5 minutes
        self.update_status()

    def add_menus(self):

        # File

        if self.standalone:
            quit_icon = QtGui.QIcon(
                os.path.join(app_info.app_media_path, 'quit.png'))
            quit_act = QtWidgets.QAction(quit_icon, 'Exit', self)
            quit_act.setStatusTip('Close the application')
            # noinspection PyUnresolvedReferences
            quit_act.triggered.connect(self.close)
            self.menu_file.addAction(quit_act)

        # Setup

        self.menu_setup_layout = self.menu_setup.addMenu("Layout")

        reset_layout = QtWidgets.QAction('Reset layout', self)
        reset_layout.setStatusTip('Reset toolbars and menu')
        # noinspection PyUnresolvedReferences
        reset_layout.triggered.connect(self.reset_layout)
        self.menu_setup_layout.addAction(reset_layout)

        resize_tabs_icons = QtWidgets.QAction('Tabs icon size', self)
        resize_tabs_icons.setStatusTip('Resize the tabs icons')
        # noinspection PyUnresolvedReferences
        resize_tabs_icons.triggered.connect(self.resize_tabs_icons)
        self.menu_setup_layout.addAction(resize_tabs_icons)

        resize_toolbars_icons = QtWidgets.QAction('Toolbars icon size', self)
        resize_toolbars_icons.setStatusTip('Resize the toolbars icons')
        # noinspection PyUnresolvedReferences
        resize_toolbars_icons.triggered.connect(self.resize_toolbars_icons)
        self.menu_setup_layout.addAction(resize_toolbars_icons)

        # Help
        self.menu_help.addAction(self.tab_info.open_online_manual_action)
        self.menu_help.addAction(self.tab_info.open_offline_manual_action)
        self.menu_help.addAction(self.tab_info.fill_bug_report_action)
        self.menu_help.addAction(self.tab_info.authors_action)
        self.menu_help.addAction(self.tab_info.show_about_action)

    # ### APP APPEARANCE ###

    def reset_layout(self) -> None:
        logger.debug("reset layout")

        self.restoreState(self.settings.value("main_window/state_default"))
        self.restoreGeometry(
            self.settings.value("main_window/geometry_default"))
        self.set_tabs_icon_size(app_info.app_tabs_icon_size)
        self.set_toolbars_icon_size(app_info.app_toolbars_icon_size)

    def resize_tabs_icons(self) -> None:
        logger.debug("resize tabs icons")
        cur_size = int(self.tabs.iconSize().width())
        # noinspection PyCallByClass
        new_size, ret = QtWidgets.QInputDialog.getInt(
            self, "Tabs", "Set tabs icon size in pixels:", cur_size, 8, 126)
        if not ret:
            return
        self.set_tabs_icon_size(new_size)

    def set_tabs_icon_size(self, icon_size: int) -> None:
        self.tabs.setIconSize(QtCore.QSize(icon_size, icon_size))

    def resize_toolbars_icons(self) -> None:
        logger.debug("resize tabs icons")
        cur_size = self.tab_arch.toolbars_icon_size()
        # noinspection PyCallByClass
        new_size, ret = QtWidgets.QInputDialog.getInt(
            self, "Toolbars", "Set toolbars icon size in pixels:", cur_size, 8,
            126)
        if not ret:
            return
        self.set_toolbars_icon_size(new_size)

    def set_toolbars_icon_size(self, icon_size: int) -> None:
        self.tab_arch.set_toolbars_icon_size(icon_size)
        if self.standalone:
            self.tab_info.set_toolbars_icon_size(icon_size)

    # ### TAB SWITCHERS ###

    def _on_tab_changed(self, idx) -> None:
        logger.debug("switch to tab #%d" % idx)
        if hasattr(self.tabs.currentWidget(), "redraw"):
            self.tabs.currentWidget().redraw()

    def switch_to_arch_tab(self) -> None:
        if self.tabs.currentIndex() != self.tab_arch_idx:
            self.tabs.setCurrentIndex(self.tab_arch_idx)

    def switch_to_compare_tab(self) -> None:
        if self.tabs.currentIndex() != self.tab_compare_idx:
            self.tabs.setCurrentIndex(self.tab_compare_idx)

    def switch_to_arch3d_tab(self) -> None:
        if self.tabs.currentIndex() != self.tab_arch3d_idx:
            self.tabs.setCurrentIndex(self.tab_arch3d_idx)

    def switch_to_info_tab(self) -> None:
        if self.tabs.currentIndex() != self.tab_info_idx:
            self.tabs.setCurrentIndex(self.tab_info_idx)

    def update_status(self) -> None:
        if not self.standalone:
            return
        msg = str()
        tokens = list()

        new_release = False
        new_bugfix = False
        latest_version = None
        try:
            req = Request(app_info.app_latest_url)
            with urlopen(req, timeout=1) as response:
                latest_version = response.read().split()[0].decode()

                cur_maj, cur_min, cur_fix = app_info.app_version.split('.')
                lat_maj, lat_min, lat_fix = latest_version.split('.')

                if int(lat_maj) > int(cur_maj):
                    new_release = True

                elif (int(lat_maj)
                      == int(cur_maj)) and (int(lat_min) > int(cur_min)):
                    new_release = True

                elif (int(lat_maj) == int(cur_maj)) and (int(lat_min) == int(cur_min)) \
                        and (int(lat_fix) > int(cur_fix)):
                    new_bugfix = True

        except (URLError, ssl.SSLError, socket.timeout) as e:
            logger.info("unable to check latest release: %s" % e)

        except ValueError as e:
            logger.info("unable to parse version: %s" % e)

        if new_release:
            logger.info("new release available: %s" % latest_version)
            tokens.append("New release available: %s" % latest_version)
            self.statusBar().setStyleSheet(
                "QStatusBar{background-color:rgba(255,0,0,128);}")

        elif new_bugfix:
            logger.info("new bugfix available: %s" % latest_version)
            tokens.append("New bugfix available: %s" % latest_version)
            self.statusBar().setStyleSheet(
                "QStatusBar{background-color:rgba(255,255,0,128);}")

        else:
            self.statusBar().setStyleSheet(self.status_bar_normal_style)

        msg += "|".join(tokens)

        self.statusBar().showMessage(msg, 3000000)

    def exception_hook(self, ex_type: type, ex_value: BaseException,
                       tb: traceback) -> None:
        sys.__excepthook__(ex_type, ex_value, tb)

        # first manage case of not being an exception (e.g., keyboard interrupts)
        if not issubclass(ex_type, Exception):
            msg = str(ex_value)
            if not msg:
                msg = ex_value.__class__.__name__
            logger.info(msg)
            self.close()
            return

        dlg = ExceptionDialog(app_info=app_info,
                              lib_info=lib_info,
                              ex_type=ex_type,
                              ex_value=ex_value,
                              tb=tb)
        ret = dlg.exec_()
        if ret == QtWidgets.QDialog.Rejected:
            if not dlg.user_triggered:
                self.close()
        else:
            logger.warning("ignored exception")

    # Quitting #

    def do_you_really_want(
            self,
            title: str = "Quit",
            text: str = "quit") -> QtWidgets.QMessageBox.StandardButton:
        msg_box = QtWidgets.QMessageBox(self)
        msg_box.setWindowTitle(title)
        msg_box.setIconPixmap(QtGui.QPixmap(app_info.app_icon_path))
        msg_box.setText('Do you really want to %s?' % text)
        msg_box.setStandardButtons(QtWidgets.QMessageBox.Yes
                                   | QtWidgets.QMessageBox.No)
        msg_box.setDefaultButton(QtWidgets.QMessageBox.No)
        return msg_box.exec_()

    def closeEvent(self, event: QtCore.QEvent) -> None:
        """ actions to be done before close the app """

        reply = QtWidgets.QMessageBox.Yes
        if self.ask_quit:
            reply = self.do_you_really_want(text="quit")

        if reply == QtWidgets.QMessageBox.Yes:

            # store current tab
            self.settings.setValue("tabs/icon_size",
                                   int(self.tabs.iconSize().width()))
            # self.settings.setValue("toolbars/icon_size", self.tab_arch.toolbars_icon_size())
            self.settings.setValue("main_window/state", self.saveState())
            self.settings.setValue("main_window/geometry", self.saveGeometry())

            event.accept()
            super().closeEvent(event)

        else:

            event.ignore()
Beispiel #9
0
import logging

from PySide2 import QtWidgets

from hyo2.abc.app.tabs.info.info_tab import InfoTab
from hyo2.abc.lib.lib_info import LibInfo
from hyo2.abc.app.app_info import AppInfo
from hyo2.abc.lib.logging import set_logging

logger = logging.getLogger(__name__)
set_logging(ns_list=["hyo2.abc"])

app = QtWidgets.QApplication([])

mw = QtWidgets.QMainWindow()

t = InfoTab(main_win=mw,
            lib_info=LibInfo(),
            app_info=AppInfo(),
            with_online_manual=True,
            with_offline_manual=True,
            with_bug_report=True,
            with_hydroffice_link=True,
            with_ccom_link=True,
            with_noaa_link=True,
            with_unh_link=True,
            with_license=True)
t.show()

sys.exit(app.exec_())