def ok(self):
        try:
            cls = self.calculate(self.input_parameters)
            self.output_parameters = cls.output_kwargs
            self.statusBar().showMessage('Calculation complete')
        except Exception as e:
            self.statusBar().showMessage(f'{e}', timeout=10 * 1e3)
            raise e

        if self.ui.p2_in_make_pdf.isChecked():
            logger.info('Making local PDF ...')
            try:
                if shutil.which('latexmk'):
                    temp = tempfile.NamedTemporaryFile(suffix='.pdf')
                    temp.close()
                    fp_pdf = temp.name
                    logger.info(f'Making local PDF ... {fp_pdf}')
                    threading.Thread(
                        target=lambda: cls.make_pdf(fp_pdf=fp_pdf)).start()
                else:
                    temp = tempfile.NamedTemporaryFile(suffix='.tex', )
                    temp.close()
                    fp_tex = temp.name
                    logger.info(f'Making online PDF ... {fp_tex}')
                    threading.Thread(target=lambda: cls.make_pdf_web(
                        fp_tex=fp_tex)).start()
            except Exception as e:
                logger.error(f'Failed to make PDF, {e}')
Example #2
0
    def init(self):
        self.setWindowTitle(self.app_name_long)
        try:
            self.setWindowIcon(
                QtGui.QPixmap(
                    path.join(__root_dir__, 'gui', 'icons',
                              'LOGO_1_80_80.png')))
        except Exception as e:
            logger.error(f'Icon file not found {e}')

        self.setStyleSheet(qt_css)

        if hasattr(self.ui, 'pushButton_ok'):
            self.ui.pushButton_ok.clicked.connect(self.ok)
        if hasattr(self.ui, 'pushButton_about'):
            if self.__about_dialog is None:
                self.__about_dialog = AboutDialog(fp_or_html=path.join(
                    __root_dir__, 'gui', 'docs', f'{self.app_id}.html'))
            self.ui.pushButton_about.clicked.connect(
                lambda: self.__about_dialog.show())
        if hasattr(self.ui, 'pushButton_example'):
            self.ui.pushButton_example.clicked.connect(self.example)

        self.adjustSize()

        threading.Thread(target=self.user_usage_stats,
                         args=[self.app_id]).start()
 def ok(self):
     try:
         self.calculate()
         self.repaint()
     except Exception as e:
         logger.error(f'{e}')
         self.statusBar().showMessage(f'{e}')
         self.repaint()
         return
Example #4
0
    def closeEvent(self, event):

        logger.debug('Terminating activated dialogs/mainwindows ...')
        for i in self.activated_dialogs:
            try:
                i.close()
            except Exception as e:
                logger.error(f'{str(e)}')

        logger.debug('All activated widgets are terminated')

        event.accept()
Example #5
0
    def __init__(self,
                 parent=None,
                 post_stats: bool = True,
                 ui=AppBaseClassUI,
                 *args,
                 **kwargs):
        self.__activated_dialogs = list()
        self.__about_dialog = None
        self.__clipboard = QtWidgets.QApplication.clipboard()

        super().__init__(parent=parent, *args, **kwargs)
        self.ui = ui()
        self.ui.setupUi(self)

        # set window title, icon and stylesheet
        self.setWindowTitle(self.app_name_long)
        try:
            self.setWindowIcon(
                QtGui.QPixmap(
                    path.join(__root_dir__, 'gui', 'icons',
                              'LOGO_1_80_80.png')))
        except Exception as e:
            logger.error(f'Icon file not found {e}')
        self.setStyleSheet(qt_css)

        # instantiate and configure signals
        try:
            self.ui.p3_submit.clicked.connect(self.ok)
        except Exception as e:
            logger.warning(f'{e}')
        try:
            self.__about_dialog = self.__about_dialog or AboutDialog(
                fp_or_html=path.join(__root_dir__, 'gui', 'docs',
                                     f'{self.app_id}.html'))
            self.ui.p3_about.clicked.connect(
                lambda: self.__about_dialog.show())
        except Exception as e:
            logger.warning(f'{e}')
        try:
            self.ui.p3_example.clicked.connect(self.example)
        except Exception as e:
            logger.warning(f'{e}')

        # post stats if required
        if post_stats:
            try:
                threading.Thread(target=self.user_usage_stats,
                                 args=[self.app_id]).start()
            except Exception as e:
                logger.warning(f'{e}')

        self.adjustSize()
Example #6
0
 def func():
     try:
         app = self.__apps[code]
         if code == '0101' or code == '0102':
             # todo: 0101 and 0102 do not run without parent
             app = app(parent=parent)
         else:
             app = app()
             parent.activated_dialogs.append(app)
         app.show()
         logger.info(f'Successfully loaded module {code}')
     except Exception as e:
         logger.error(f'Failed to load module {code}, {e}')
         raise e
Example #7
0
 def user_usage_stats(content: str, is_dev: bool = 'dev' in __version__):
     if is_dev:
         logger.debug(f'DEV VERSION, STATS POST IGNORED FOR {content}')
         return
     try:
         logger.debug(f'STATS POST STARTED FOR {content}')
         rp = post_to_knack_user_usage_stats(
             user=str(getlogin()),  # user indicator
             version=__version__,  # current app version
             date=datetime.now().strftime(
                 "%d%m%Y %H:%M%p"),  # example "03/28/2014 10:30pm"
             content=content  # action is the current app id
         )
         logger.info(f'STATS POST STATUS {rp}')
         logger.debug(f'{rp.text}')
     except Exception as e:
         logger.error(f'User stats post failed {e}')
Example #8
0
 def user_usage_stats(content: str, is_dev: bool = 'dev' in __version__):
     if is_dev:
         logger.debug(
             f'Post usage stats ignored for dev version, {content}')
         return
     try:
         logger.info(f'Post usage stats started {content} ...')
         rp = post_to_knack_user_usage_stats(
             user=str(getlogin()),  # user indicator
             version=__version__,  # current app version
             date=datetime.now().strftime(
                 "%d%m%Y %H:%M%p"),  # example "03/28/2014 10:30pm"
             content=content  # action is the current app id
         )
         logger.info(f'Successfully posted usage stats, {rp}')
         logger.debug(f'{rp.text}')
     except Exception as e:
         logger.error(f'Failed to post usage stats, {e}')
    def ok(self):
        """Placeholder method to be overridden by child classes.
        This method is expected to be triggered upon clicking the 'OK' or 'Calculate' button. The following comments
        are suggested procedure to be followed. This method is also connected by keyboard shortcut 'Enter'"""

        # Step 1. Get parameters from UI
        try:
            input_parameters = self.input_parameters
        except Exception as e:
            logger.error(f'Failed to parse inputs, {e}')
            self.statusBar().showMessage(f'Failed to parse inputs, {e}')
            return e

        # Step 2. Perform analysis
        # work out distribution
        try:
            assert hasattr(stats, input_parameters['dist_name'])
            output_parameters = self.solve_dist(**input_parameters)
        except Exception as e:
            logger.error(f'Failed to make distribution, {e}')
            self.statusBar().showMessage(f'Failed to make distribution, {e}')
            return e

        # Step 3. Cast result onto UI
        try:
            self.output_parameters = output_parameters
        except Exception as e:
            logger.error(f'Failed to output results, {e}')
            self.statusBar().showMessage(f'Failed to output results, {e}')
            return e

        try:
            self.show_results_in_figure()
        except Exception as e:
            logger.error(f'Failed to make plots, {e}')
            self.statusBar().showMessage(f'Failed to make plots, {e}')
            return e

        if not self.ui.p2_in_sample_value.isEnabled():
            self.ui.p2_in_sample_value.setEnabled(True)
            self.ui.p2_in_cdf.setEnabled(True)

        logger.info(f'Calculation complete')
        self.ui.statusbar.showMessage('Calculation complete')
        self.repaint()
Example #10
0
    def check_update(self):
        """
        This method will be called in a thread! Try to avoid competing with the main GUI thread, e.g. avoid repaint etc.
        """

        # parse remote version info
        logger.info('Parsing update data ...')
        target = ''.join([
            chr(ord(v) + i % 10) for i, v in enumerate(__remote_version_url__)
        ])
        try:
            self.update_data = requests.get(target).json()
            logger.info(f'Successfully parsed update data.')
            logger.debug(f'{str(self.update_data)}.')
        except Exception as e:
            self.update_data = {
            }  # assign an empty dict if failed to parse remote version info
            logger.error(f'Failed to parse update data, {e}.')
            return

        logger.info('Analysing update data ...')
        try:
            latest_version = self.update_data['latest_version']
            logger.info(
                f'Successfully parsed the latest version, {latest_version}')
        except Exception as e:
            logger.error(
                f'Failed to get the latest version from update data, {e}')
            return

        try:
            if version.parse(latest_version) <= version.parse(__version__):
                self.ui.label_version.setStyleSheet('color: grey;')
                logger.info(f'No updates available')
                return
        except Exception as e:
            logger.error(f'Failed to analyse update data, {e}')
            return
        '''
        if no updates available -> version text change from black to grey
        
        if local version is lower than remote version, i.e. updates available, follow the procedures below:
        
            a) if local version is executable -> show update available message in black
            b) if local version IS NOT executable -> disable all modules (buttons) and show update message in black

        if failed to parse remote info or no local version specific data found in remote version data, leave version text in black colour.
        '''

        try:
            specific_remote_version_data = self.update_data[__version__.split(
                '.dev')[0] if '.dev' in __version__ else __version__]
            logger.info(f'Successfully parsed local version from update data')
            logger.debug(f'{specific_remote_version_data}')
        except Exception as e:
            logger.error(
                f'Failed to parse local version from update data, {str(e)}')
            return

        # parse `is_executable` from remote version info
        # this will be used to check whether local version is executable
        try:
            is_local_version_executable = specific_remote_version_data[
                'is_executable']
            logger.info(
                f'Successfully parsed `is_executable`, {is_local_version_executable}'
            )
            if is_local_version_executable is False:
                logger.warning(
                    f'Local version IS NOT executable, all features will be disabled'
                )
                self.is_executable = is_local_version_executable
                self.Signals.check_update_complete.emit(self.is_executable)
        except Exception as e:
            logger.error(f'Failed to parse `is_executable`, {e}')
            return

        # parse `is_upgradable` from remote version info
        # this will be used to display upgrade notification
        try:
            is_local_version_upgradable = specific_remote_version_data[
                'is_upgradable']
            logger.info(
                f'Successfully parsed `is_upgradable`, {is_local_version_upgradable}'
            )
        except Exception as e:
            logger.error(f'Failed to parse `is_upgradable`, {e}.')
            return

        # parse `executable_download_url` from remote version info
        # this will be used to display upgrade notification
        try:
            try:
                upgrade_executable_url = specific_remote_version_data[
                    'executable_download_url']
                logger.info(
                    f'Successfully parsed `executable_download_url`, {upgrade_executable_url}'
                )
            except KeyError:
                upgrade_executable_url = self.update_data[
                    'latest_executable_download_url']
                logger.info(
                    f'Successfully parsed `latest_executable_download_url`, {upgrade_executable_url}'
                )
            self.new_version_update_url = upgrade_executable_url
        except Exception as e:
            # if both `executable_download_url` and `latest_executable_download_url` not exist, assign None and
            # print an indicative message.
            logger.error(
                f'Failed to parse `executable_download_url` or `latest_executable_download_url`, {e}'
            )
            return

        if not is_local_version_executable:
            version_label_text = f'Running version {__version__}. A new version {latest_version} is available. Click here to download.'
        elif is_local_version_upgradable:
            version_label_text = f'This version {__version__} is disabled. A new version {latest_version} is available. Click here to download.'
        else:

            version_label_text = None
            self.ui.label_version.setStyleSheet('color: grey;')

        # update gui label text and tips
        if version_label_text:
            self.ui.label_version.setText(version_label_text)
            self.ui.label_version.setStatusTip(version_label_text)
            self.ui.label_version.setToolTip(version_label_text)