Example #1
0
class Application(QtCore.QObject):
    """
    Sets up the Qt Application, the main window and the various controllers.

    The application class contains references to the main window user interface
    and to the various controllers so that they can collaborate each others.
    """
    _report_exception_requested = QtCore.pyqtSignal(object, str)

    def apply_mimetypes_preferences(self):
        for ext in Settings().all_extensions:
            mimetypes.add_type('text/x-cobol', ext)
            mimetypes.add_type('text/x-cobol', ext.upper())

    def __init__(self, parse_args=True):
        super().__init__()
        if system.darwin:
            Application._osx_init()
        self._reported_tracebacks = []
        self._old_except_hook = sys.excepthook
        sys.excepthook = self._except_hook
        self._report_exception_requested.connect(self._report_exception)
        if hasattr(sys, 'frozen') and sys.platform == 'win32':
            sys.stdout = open(os.path.join(system.get_cache_directory(),
                                           'ocide_stdout.log'), 'w')
            sys.stderr = open(os.path.join(system.get_cache_directory(),
                                           'ocide_stderr.log'), 'w')
        self.app = QtWidgets.QApplication(sys.argv)
        if parse_args and not system.darwin:
            args = self.parse_args()
            verbose = args.verbose
            files = args.files
        else:
            verbose = False
            files = []
        logger.setup_logging(__version__, debug=verbose or Settings().verbose)
        self.name = 'OpenCobolIDE'
        self.version = __version__
        self.title = '%s %s' % (self.name, self.version)

        self.apply_mimetypes_preferences()

        self.win = MainWindow()
        self.win.setWindowTitle(self.title)
        self.file = FileController(self)
        self.view = ViewController(self)
        self.home = HomeController(self)
        self.edit = EditController(self)
        self.cobol = CobolController(self)
        self.help = HelpController(self)

        self.view.show_perspective(Settings().perspective)
        self.view.show_home_page()

        self.update_app_style()

        try:
            check_compiler()
        except CompilerNotFound:
            msg = 'Failed to find a working GnuCOBOL compiler!\n' \
                "The IDE will continue to work but you won't be able to " \
                'compile...'
            if system.windows:
                msg += '\n\nTip: Ensure that there is no additional ' \
                    'installation of MinGW in %s:\MinGW' % sys.executable[0]
            QtWidgets.QMessageBox.warning(
                self.win, 'COBOL compiler not found or not working', msg)
        else:
            _logger().info('GnuCOBOL version: %s',
                           GnuCobolCompiler.get_version())
        # open specified files
        for f in files:
            self.file.open_file(f)

    def restart(self):
        """
        Restarts the IDE.
        """
        if hasattr(sys, 'frozen'):
            QtCore.QProcess.startDetached(sys.executable)
        else:
            QtCore.QProcess.startDetached(sys.executable, sys.argv)
        sys.exit(0)

    def close(self):
        self.view = None
        self.cobol = None
        self.edit = None
        self.file = None
        self.win = None
        self.home = None
        self.help = None

    def update_app_style(self):
        if Settings().dark_style:
            try:
                import qdarkstyle
            except ImportError:
                Settings().dark_style = False
            else:
                qt_api = os.environ[QT_API]
                if qt_api in PYQT5_API:
                    qss = qdarkstyle.load_stylesheet_pyqt5()
                else:
                    qss = qdarkstyle.load_stylesheet(qt_api in PYSIDE_API)
                self.app.setStyleSheet(qss)
                return
        self.app.setStyleSheet('')

    def run(self):
        """
        Run the Qt main loop.
        """
        if Settings().fullscreen:
            self.win.showFullScreen()
        else:
            self.win.showMaximized()
        return self.app.exec_()

    @staticmethod
    def _osx_init():
        """
        Mac OSX specific initialisation, adds missing path to the PATH
        environment variable (see github issue #40).

        """
        #
        paths = ['/bin', '/sbin', '/usr/bin', '/usr/sbin', '/usr/local/bin',
                 '/usr/local/sbin', '/opt/bin', '/opt/sbin', '/opt/local/bin',
                 '/opt/local/sbin']
        os.environ['PATH'] = ':'.join(paths)

    def exit(self):
        """
        Closes all top level windows and quits the application (without
        prompting the user, if you need to prompt the user, use
        Application.file.quit())
        """
        self.app.closeAllWindows()
        self.close()

    def parse_args(self):
        parser = argparse.ArgumentParser(
            description='Simple and lightweight COBOL IDE.')
        parser.add_argument('files', type=str, nargs='*',
                            help='List of files to open, if any')
        parser.add_argument('--verbose', dest='verbose', action='store_true',
                            help='Verbose mode will enable debug and info '
                                 'messages to be shown in the application log')
        return parser.parse_args()

    def _except_hook(self, exc_type, exc_val, tb):
        tb = '\n'.join([''.join(traceback.format_tb(tb)),
                        '{0}: {1}'.format(exc_type.__name__, exc_val)])
        # exception might come from another thread, use a signal
        # so that we can be sure we will show the bug report dialog from
        # the main gui thread.
        self._report_exception_requested.emit(exc_val, tb)

    def _report_exception(self, exc, tb):
        try:
            _logger().critical('unhandled exception:\n%s', tb)
            _tb = tb
            if isinstance(exc, UnicodeDecodeError):
                # This might be the same exception in the same file but at another position
                # in the stream
                _tb = tb.splitlines()[-4]
            if _tb in self._reported_tracebacks:
                return
            self._reported_tracebacks.append(_tb)
            title = '[Unhandled exception] %s' % exc.__class__.__name__
            description = 'An unhandled exception has occured:\n\n'\
                          '%s\n\nWould like to send a bug report to the ' \
                          'development team?' % tb
            answer = QtWidgets.QMessageBox.critical(
                self.win, title, description,
                QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
                QtWidgets.QMessageBox.Yes)
            if answer == QtWidgets.QMessageBox.Yes:
                description = '## Steps to reproduce\n\nPLEASE DESCRIBE '\
                    'THE CONTEXT OF THIS BUG AND THE STEPS TO REPRODUCE!\n\n'\
                    '## Traceback\n\n```\n%s\n```' % tb
                DlgReportBug.report_bug(
                    self.win, title=title, description=description)

        except Exception:
            _logger().exception('exception in excepthook')
Example #2
0
class Application(QtCore.QObject):
    """
    Sets up the Qt Application, the main window and the various controllers.

    The application class contains references to the main window user interface
    and to the various controllers so that they can collaborate each others.
    """
    def apply_mimetypes_preferences(self):
        for ext in Settings().all_extensions:
            mimetypes.add_type('text/x-cobol', ext)
            mimetypes.add_type('text/x-cobol', ext.upper())

    def __init__(self, parse_args=True):
        super().__init__()
        if system.darwin:
            Application._osx_init()
        self.app = QtWidgets.QApplication(sys.argv)

        self._reported_tracebacks = []
        qcrash.get_system_information = system.get_system_infos
        qcrash.get_application_log = logger.get_application_log
        qcrash.install_backend(
            qcrash.backends.GithubBackend(QCRASH_GH_OWNER, QCRASH_GH_REPO),
            qcrash.backends.EmailBackend(QCRASH_EMAIL, 'OpenCobolIDE'))
        qcrash.set_qsettings(Settings()._settings)
        qcrash.install_except_hook(except_hook=self._report_exception)
        # if hasattr(sys, 'frozen') and sys.platform == 'win32':
        #     sys.stdout = open(os.path.join(system.get_cache_directory(),
        #                                    'ocide_stdout.log'), 'w')
        #     sys.stderr = open(os.path.join(system.get_cache_directory(),
        #                                    'ocide_stderr.log'), 'w')
        if parse_args and not system.darwin:
            files = self.handle_command_line_args()
        else:
            files = []
        _logger().info('files to open: %r' % files)
        self.name = 'OpenCobolIDE'
        self.version = __version__
        self.title = '%s %s' % (self.name, self.version)

        self.apply_mimetypes_preferences()

        self.win = MainWindow()
        self.win.setWindowTitle(self.title)
        self.file = FileController(self)
        self.view = ViewController(self)
        self.home = HomeController(self)
        self.edit = EditController(self)
        self.cobol = CobolController(self)
        self.help = HelpController(self)
        self.win.app = self

        self.view.show_perspective(Settings().perspective)

        self.update_app_style()

        try:
            check_compiler()
        except CompilerNotFound:
            msg = 'Failed to find a working GnuCOBOL compiler!\n' \
                "The IDE will continue to work but you won't be able to " \
                'compile...'
            if system.windows:
                msg += '\n\nTip: Ensure that there is no additional ' \
                    'installation of MinGW in %s:\MinGW' % sys.executable[0]
            QtWidgets.QMessageBox.warning(
                self.win, 'COBOL compiler not found or not working', msg)
        else:
            _logger().info('GnuCOBOL version: %s',
                           GnuCobolCompiler.get_version(include_all=False))
        self._files = files

    def restart(self):
        """
        Restarts the IDE.
        """
        if hasattr(sys, 'frozen'):
            QtCore.QProcess.startDetached(sys.executable)
        else:
            QtCore.QProcess.startDetached(sys.executable, sys.argv)
        sys.exit(0)

    def close(self):
        self.view = None
        self.cobol = None
        self.edit = None
        self.file = None
        self.win = None
        self.home = None
        self.help = None

    def update_app_style(self):
        if Settings().dark_style:
            try:
                import qdarkstyle
            except ImportError:
                Settings().dark_style = False
            else:
                qt_api = os.environ[QT_API]
                if qt_api in PYQT5_API:
                    qss = qdarkstyle.load_stylesheet_pyqt5()
                else:
                    qss = qdarkstyle.load_stylesheet(qt_api in PYSIDE_API)
                self.app.setStyleSheet(qss)
                return
        self.app.setStyleSheet('')

    def run(self):
        """
        Run the Qt main loop.
        """
        if Settings().fullscreen:
            self.win.showFullScreen()
        else:
            self.win.show()
            self.view.restore_state()
            self.view.show_home_page()
            if self._files:
                # open specified files
                for f in self._files:
                    self.file.open_file(f)
        return self.app.exec_()

    @staticmethod
    def _osx_init():
        """
        Mac OSX specific initialisation, adds missing path to the PATH
        environment variable (see github issue #40).

        """
        #
        paths = ['/bin', '/sbin', '/usr/bin', '/usr/sbin', '/usr/local/bin',
                 '/usr/local/sbin', '/opt/bin', '/opt/sbin', '/opt/local/bin',
                 '/opt/local/sbin']
        os.environ['PATH'] = ':'.join(paths)

    def exit(self):
        """
        Closes all top level windows and quits the application (without
        prompting the user, if you need to prompt the user, use
        Application.file.quit())
        """
        self.app.closeAllWindows()
        self.close()

    def handle_command_line_args(self):
        args = self.parse_args()
        files = args.files

        # setup logger
        debug = args.verbose or Settings().verbose
        logger.setup_logging(__version__, level=Settings().log_level)

        # show runtime env
        if args.runtime_env:
            print('OpenCobolIDE %s' % __version__)
            for k, v in sorted(DlgAbout.get_runtime_env().items(),
                               key=lambda x: x[0]):
                print('%s %s' % (k, v))
            sys.exit(0)

        # show cobc runtime env
        if args.cobc_runtime_env:
            print(DlgAbout.get_cobc_runtime_env())
            sys.exit(0)

        # import preferences
        if args.conf:
            try:
                with open(args.conf, 'rb') as f:
                    Settings().import_from_dict(pickle.load(f))
            except (ValueError, IOError, OSError):
                _logger().exception('failed to restore preferences from %r',
                                    args.conf)
            else:
                _logger().info('preferences imported from %r', args.conf)

        # compile specified files
        if args.compile:
            thread = CompilationThread()
            for path in files:
                if os.path.exists(path):
                    CobolController.clean_file(path)
                    thread.file_path = path
                    thread.run()
                else:
                    print('cannot compile %r, file not found')
            sys.exit(0)

        return files

    def parse_args(self):
        parser = argparse.ArgumentParser(
            description='Simple and lightweight COBOL IDE.')
        parser.add_argument('files', type=str, nargs='*',
                            help='List of files to open, if any')
        parser.add_argument('--verbose', dest='verbose', action='store_true',
                            help='Verbose mode will enable debug and info '
                                 'messages to be shown in the application log')
        parser.add_argument(
            '--runtime-env', dest='runtime_env', action='store_true',
            help='Display the application runtime environment.')

        parser.add_argument(
            '--cobc-runtime-env', dest='cobc_runtime_env',
            action='store_true',
            help='Display the compiler runtime environment.')

        parser.add_argument(
            '--compile', dest='compile',
            action='store_true',
            help='Compile the specified files and exits.')

        parser.add_argument(
            '--conf', dest='conf',
            help='Specify a configuration file (previously exported from '
            'within the IDE (File->Export preferences))')

        return parser.parse_args()

    def _except_hook(self, exc_type, exc_val, tb):
        tb = '\n'.join([''.join(traceback.format_tb(tb)),
                        '{0}: {1}'.format(exc_type.__name__, exc_val)])
        # exception might come from another thread, use a signal
        # so that we can be sure we will show the bug report dialog from
        # the main gui thread.
        self._report_exception_requested.emit(exc_val, tb)

    def _report_exception(self, exc, tb):
        try:
            _logger().critical('unhandled exception:\n%s', tb)
            _tb = tb
            if isinstance(exc, UnicodeDecodeError):
                # This might be the same exception in the same file but at
                # another position in the stream
                _tb = tb.splitlines()[-4]
            if _tb in self._reported_tracebacks:
                return
            self._reported_tracebacks.append(_tb)
            title = '[Unhandled exception] %s' % exc.__class__.__name__
            description = 'An unhandled exception has occured:\n\n'\
                          '%s\n\nWould like to send a bug report to the ' \
                          'development team?' % tb
            answer = QtWidgets.QMessageBox.critical(
                self.win, title, description,
                QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
                QtWidgets.QMessageBox.Yes)
            if answer == QtWidgets.QMessageBox.Yes:
                qcrash.show_report_dialog(
                    parent=self.win, window_icon=self.win.windowIcon(),
                    window_title="Report unhandled exception",
                    issue_title=title, traceback=tb)
        except Exception:
            _logger().exception('exception in excepthook')
Example #3
0
class Application(QtCore.QObject):
    """
    Sets up the Qt Application, the main window and the various controllers.

    The application class contains references to the main window user interface
    and to the various controllers so that they can collaborate each others.
    """
    def apply_mimetypes_preferences(self):
        for ext in Settings().all_extensions:
            mimetypes.add_type('text/x-cobol', ext)
            mimetypes.add_type('text/x-cobol', ext.upper())

    def __init__(self, parse_args=True):
        super().__init__()
        if system.darwin:
            Application._osx_init()
        self.app = QtWidgets.QApplication(sys.argv)

        self._reported_tracebacks = []
        qcrash.get_system_information = system.get_system_infos
        qcrash.get_application_log = logger.get_application_log
        qcrash.install_backend(
            qcrash.backends.GithubBackend(QCRASH_GH_OWNER, QCRASH_GH_REPO),
            qcrash.backends.EmailBackend(QCRASH_EMAIL, 'OpenCobolIDE'))
        qcrash.set_qsettings(Settings()._settings)
        qcrash.install_except_hook(except_hook=self._report_exception)
        # if hasattr(sys, 'frozen') and sys.platform == 'win32':
        #     sys.stdout = open(os.path.join(system.get_cache_directory(),
        #                                    'ocide_stdout.log'), 'w')
        #     sys.stderr = open(os.path.join(system.get_cache_directory(),
        #                                    'ocide_stderr.log'), 'w')
        if parse_args and not system.darwin:
            files = self.handle_command_line_args()
        else:
            files = []
        _logger().info('files to open: %r' % files)
        self.name = 'OpenCobolIDE'
        self.version = __version__
        self.title = '%s %s' % (self.name, self.version)

        self.apply_mimetypes_preferences()

        self.win = MainWindow()
        self.win.setWindowTitle(self.title)
        self.file = FileController(self)
        self.view = ViewController(self)
        self.home = HomeController(self)
        self.edit = EditController(self)
        self.cobol = CobolController(self)
        self.help = HelpController(self)
        self.win.app = self

        self.view.show_perspective(Settings().perspective)

        self.update_app_style()

        try:
            check_compiler()
        except CompilerNotFound:
            msg = 'Failed to find a working GnuCOBOL compiler!\n' \
                "The IDE will continue to work but you won't be able to " \
                'compile...'
            if system.windows:
                msg += '\n\nTip: Ensure that there is no additional ' \
                    'installation of MinGW in %s:\MinGW' % sys.executable[0]
            QtWidgets.QMessageBox.warning(
                self.win, 'COBOL compiler not found or not working', msg)
        else:
            _logger().info('GnuCOBOL version: %s',
                           GnuCobolCompiler.get_version(include_all=False))
        self._files = files

    def restart(self):
        """
        Restarts the IDE.
        """
        if hasattr(sys, 'frozen'):
            QtCore.QProcess.startDetached(sys.executable)
        else:
            QtCore.QProcess.startDetached(sys.executable, sys.argv)
        sys.exit(0)

    def close(self):
        self.view = None
        self.cobol = None
        self.edit = None
        self.file = None
        self.win = None
        self.home = None
        self.help = None

    def update_app_style(self):
        if Settings().dark_style:
            try:
                import qdarkstyle
            except ImportError:
                Settings().dark_style = False
            else:
                qt_api = os.environ[QT_API]
                if qt_api in PYQT5_API:
                    qss = qdarkstyle.load_stylesheet_pyqt5()
                else:
                    qss = qdarkstyle.load_stylesheet(qt_api in PYSIDE_API)
                self.app.setStyleSheet(qss)
                return
        elif system.windows and QtCore.QSysInfo.windowsVersion(
        ) == QtCore.QSysInfo.WV_WINDOWS10:
            self.app.setStyleSheet('QToolBar { background-color: white;};')
        else:
            self.app.setStyleSheet('')

    def run(self):
        """
        Run the Qt main loop.
        """
        if Settings().fullscreen:
            self.win.showFullScreen()
        else:
            self.win.show()
            self.view.restore_state()
            self.view.show_home_page()
            if self._files:
                # open specified files
                for f in self._files:
                    self.file.open_file(f)
        return self.app.exec_()

    @staticmethod
    def _osx_init():
        """
        Mac OSX specific initialisation, adds missing path to the PATH
        environment variable (see github issue #40).

        """
        #
        paths = [
            '/bin', '/sbin', '/usr/bin', '/usr/sbin', '/usr/local/bin',
            '/usr/local/sbin', '/opt/bin', '/opt/sbin', '/opt/local/bin',
            '/opt/local/sbin'
        ]
        os.environ['PATH'] = ':'.join(paths)

    def exit(self):
        """
        Closes all top level windows and quits the application (without
        prompting the user, if you need to prompt the user, use
        Application.file.quit())
        """
        self.app.closeAllWindows()
        self.close()

    def handle_command_line_args(self):
        args = self.parse_args()
        files = args.files

        # setup logger
        debug = args.verbose or Settings().verbose
        logger.setup_logging(__version__, level=Settings().log_level)

        # show runtime env
        if args.runtime_env:
            print(('OpenCobolIDE %s' % __version__))
            for k, v in sorted(list(DlgAbout.get_runtime_env().items()),
                               key=lambda x: x[0]):
                print(('%s %s' % (k, v)))
            sys.exit(0)

        # show cobc runtime env
        if args.cobc_runtime_env:
            print((DlgAbout.get_cobc_runtime_env()))
            sys.exit(0)

        # import preferences
        if args.conf:
            try:
                with open(args.conf, 'rb') as f:
                    Settings().import_from_dict(pickle.load(f))
            except (ValueError, IOError, OSError):
                _logger().exception('failed to restore preferences from %r',
                                    args.conf)
            else:
                _logger().info('preferences imported from %r', args.conf)

        # compile specified files
        if args.compile:
            thread = CompilationThread()
            for path in files:
                if os.path.exists(path):
                    CobolController.clean_file(path)
                    thread.file_path = path
                    thread.run()
                else:
                    print('cannot compile %r, file not found')
            sys.exit(0)

        return files

    def parse_args(self):
        parser = argparse.ArgumentParser(
            description='Simple and lightweight COBOL IDE.')
        parser.add_argument('files',
                            type=str,
                            nargs='*',
                            help='List of files to open, if any')
        parser.add_argument('--verbose',
                            dest='verbose',
                            action='store_true',
                            help='Verbose mode will enable debug and info '
                            'messages to be shown in the application log')
        parser.add_argument(
            '--runtime-env',
            dest='runtime_env',
            action='store_true',
            help='Display the application runtime environment.')

        parser.add_argument('--cobc-runtime-env',
                            dest='cobc_runtime_env',
                            action='store_true',
                            help='Display the compiler runtime environment.')

        parser.add_argument('--compile',
                            dest='compile',
                            action='store_true',
                            help='Compile the specified files and exits.')

        parser.add_argument(
            '--conf',
            dest='conf',
            help='Specify a configuration file (previously exported from '
            'within the IDE (File->Export preferences))')

        return parser.parse_args()

    def _except_hook(self, exc_type, exc_val, tb):
        tb = '\n'.join([
            ''.join(traceback.format_tb(tb)),
            '{0}: {1}'.format(exc_type.__name__, exc_val)
        ])
        # exception might come from another thread, use a signal
        # so that we can be sure we will show the bug report dialog from
        # the main gui thread.
        self._report_exception_requested.emit(exc_val, tb)

    def _report_exception(self, exc, tb):
        try:
            _logger().critical('unhandled exception:\n%s', tb)
            _tb = tb
            if isinstance(exc, UnicodeDecodeError):
                # This might be the same exception in the same file but at
                # another position in the stream
                _tb = tb.splitlines()[-4]
            if _tb in self._reported_tracebacks:
                return
            self._reported_tracebacks.append(_tb)
            title = '[Unhandled exception] %s' % exc.__class__.__name__
            description = 'An unhandled exception has occured:\n\n'\
                          '%s\n\nWould you like to send a bug report to the ' \
                          'development team?' % tb
            answer = QtWidgets.QMessageBox.critical(
                self.win, title, description,
                QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
                QtWidgets.QMessageBox.Yes)
            if answer == QtWidgets.QMessageBox.Yes:
                qcrash.show_report_dialog(
                    parent=self.win,
                    window_icon=self.win.windowIcon(),
                    window_title="Report unhandled exception",
                    issue_title=title,
                    traceback=tb)
        except Exception:
            _logger().exception('exception in excepthook')
Example #4
0
class Application:
    """
    Sets up the Qt Application, the main window and the various controllers.

    The application class contains references to the main window user interface
    and to the various controllers so that they can collaborate each others.
    """

    def apply_mimetypes_preferences(self):
        for ext in Settings().all_extensions:
            mimetypes.add_type('text/x-cobol', ext)
            mimetypes.add_type('text/x-cobol', ext.upper())

    def __init__(self, parse_args=True):
        if hasattr(sys, 'frozen') and sys.platform == 'win32':
            sys.stdout = open(os.path.join(system.get_cache_directory(),
                                           'ocide_stdout.log'), 'w')
            sys.stderr = open(os.path.join(system.get_cache_directory(),
                                           'ocide_stderr.log'), 'w')
        self.init_env()
        self.app = QtWidgets.QApplication(sys.argv)
        if parse_args and not system.darwin:
            args = self.parse_args()
            verbose = args.verbose
            files = args.files
        else:
            verbose = False
            files = []
        logger.setup_logging(__version__, debug=verbose or Settings().verbose)
        self.name = 'OpenCobolIDE'
        self.version = __version__
        self.title = '%s %s' % (self.name, self.version)

        self.apply_mimetypes_preferences()

        self.win = MainWindow()
        self.win.setWindowTitle(self.title)
        self.file = FileController(self)
        self.view = ViewController(self)
        self.home = HomeController(self)
        self.edit = EditController(self)
        self.cobol = CobolController(self)
        self.help = HelpController(self)

        self.view.show_perspective(Settings().perspective)
        self.view.show_home_page()

        self.update_app_style()

        try:
            check_compiler()
        except CompilerNotFound as e:
            QtWidgets.QMessageBox.warning(
                self.win, 'COBOL compiler not found',
                'Failed to find GnuCOBOL compiler!\n\n%s\n\n'
                "The IDE will continue to work but you won't be able to "
                'compile any file...' % e)
        else:
            _logger().info('GnuCOBOL version: %s',
                           GnuCobolCompiler.get_version())
        # open specified files
        for f in files:
            self.file.open_file(f)

    def restart(self):
        """
        Restarts the IDE.
        """
        if hasattr(sys, 'frozen'):
            QtCore.QProcess.startDetached(sys.executable)
        else:
            QtCore.QProcess.startDetached(sys.executable, sys.argv)
        sys.exit(0)

    def close(self):
        self.view = None
        self.cobol = None
        self.edit = None
        self.file = None
        self.win = None
        self.home = None
        self.help = None

    def update_app_style(self):
        if Settings().dark_style:
            try:
                import qdarkstyle
            except ImportError:
                Settings().dark_style = False
            else:
                qt_api = os.environ[QT_API]
                if qt_api in PYQT5_API:
                    qss = qdarkstyle.load_stylesheet_pyqt5()
                else:
                    qss = qdarkstyle.load_stylesheet(qt_api in PYSIDE_API)
                self.app.setStyleSheet(qss)
                return
        self.app.setStyleSheet('')

    def run(self):
        """
        Run the Qt main loop.
        """
        if Settings().fullscreen:
            self.win.showFullScreen()
        else:
            self.win.showMaximized()
        return self.app.exec_()

    @classmethod
    def init_env(cls):
        """
        Inits the environment
        :return:
        """
        s = Settings()
        if s.path_enabled:
            os.environ['PATH'] = s.path + os.pathsep + os.environ['PATH']
        else:
            try:
                os.environ['PATH'] = _original_env['PATH']
            except KeyError:
                pass
        if s.cob_config_dir_enabled:
            os.environ['COB_CONFIG_DIR'] = s.cob_config_dir
        else:
            try:
                os.environ['COB_CONFIG_DIR'] = _original_env['COB_CONFIG_DIR']
            except KeyError:
                if 'COB_CONFIG_DIR' in os.environ:
                    os.environ['COB_CONFIG_DIR'] = ''
        if s.cob_copy_dir_enabled:
            os.environ['COB_COPY_DIR'] = s.cob_copy_dir
        else:
            try:
                os.environ['COB_COPY_DIR'] = _original_env['COB_COPY_DIR']
            except KeyError:
                if 'COB_COPY_DIR' in os.environ:
                    os.environ['COB_COPY_DIR'] = ''
        if s.cob_include_path_enabled:
            os.environ['COB_INCLUDE_PATH'] = s.cob_include_path
        else:
            try:
                os.environ['COB_INCLUDE_PATH'] = _original_env[
                    'COB_INCLUDE_PATH']
            except KeyError:
                if 'COB_INCLUDE_PATH' in os.environ:
                    os.environ['COB_INCLUDE_PATH'] = ''
        if s.cob_lib_path_enabled:
            os.environ['COB_LIB_PATH'] = s.cob_lib_path
        else:
            try:
                os.environ['COB_LIB_PATH'] = _original_env['COB_LIB_PATH']
            except KeyError:
                if 'COB_LIB_PATH' in os.environ:
                    os.environ['COB_LIB_PATH'] = ''
        if system.darwin:
            Application._osx_init()

    @staticmethod
    def _osx_init():
        """
        Mac OSX specific initialisation, adds missing path to the PATH
        environment variable (see github issue #40).

        """
        #
        paths = ['/bin', '/sbin', '/usr/bin', '/usr/sbin', '/usr/local/bin',
                 '/usr/local/sbin', '/opt/bin', '/opt/sbin', '/opt/local/bin',
                 '/opt/local/sbin']
        os.environ['PATH'] = ':'.join(paths)

    def exit(self):
        """
        Closes all top level windows and quits the application (without
        prompting the user, if you need to prompt the user, use
        Application.file.quit())
        """
        self.app.closeAllWindows()
        self.close()

    def parse_args(self):
        parser = argparse.ArgumentParser(
            description='Simple and lightweight COBOL IDE.')
        parser.add_argument('files', type=str, nargs='*',
                            help='List of files to open, if any')
        parser.add_argument('--verbose', dest='verbose', action='store_true',
                            help='Verbose mode will enable debug and info '
                                 'messages to be shown in the application log')
        return parser.parse_args()
Example #5
0
class Application:
    """
    Sets up the Qt Application, the main window and the various controllers.

    The application class contains references to the main window user interface
    and to the various controllers so that they can collaborate each others.
    """
    def apply_mimetypes_preferences(self):
        for ext in Settings().all_extensions:
            mimetypes.add_type('text/x-cobol', ext)
            mimetypes.add_type('text/x-cobol', ext.upper())

    def __init__(self, parse_args=True):
        if hasattr(sys, 'frozen') and sys.platform == 'win32':
            sys.stdout = open(
                os.path.join(system.get_cache_directory(), 'ocide_stdout.log'),
                'w')
            sys.stderr = open(
                os.path.join(system.get_cache_directory(), 'ocide_stderr.log'),
                'w')
        self.init_env()
        self.app = QtWidgets.QApplication(sys.argv)
        if parse_args and not system.darwin:
            args = self.parse_args()
            verbose = args.verbose
            files = args.files
        else:
            verbose = False
            files = []
        logger.setup_logging(__version__, debug=verbose or Settings().verbose)
        self.name = 'OpenCobolIDE'
        self.version = __version__
        self.title = '%s %s' % (self.name, self.version)

        self.apply_mimetypes_preferences()

        self.win = MainWindow()
        self.win.setWindowTitle(self.title)
        self.file = FileController(self)
        self.view = ViewController(self)
        self.home = HomeController(self)
        self.edit = EditController(self)
        self.cobol = CobolController(self)
        self.help = HelpController(self)

        self.view.show_perspective(Settings().perspective)
        self.view.show_home_page()

        self.update_app_style()

        try:
            check_compiler()
        except CompilerNotFound as e:
            QtWidgets.QMessageBox.warning(
                self.win, 'COBOL compiler not found',
                'Failed to find GnuCOBOL compiler!\n\n%s\n\n'
                "The IDE will continue to work but you won't be able to "
                'compile any file...' % e)
        else:
            _logger().info('GnuCOBOL version: %s',
                           GnuCobolCompiler.get_version())
        # open specified files
        for f in files:
            self.file.open_file(f)

    def restart(self):
        """
        Restarts the IDE.
        """
        if hasattr(sys, 'frozen'):
            QtCore.QProcess.startDetached(sys.executable)
        else:
            QtCore.QProcess.startDetached(sys.executable, sys.argv)
        sys.exit(0)

    def close(self):
        self.view = None
        self.cobol = None
        self.edit = None
        self.file = None
        self.win = None
        self.home = None
        self.help = None

    def update_app_style(self):
        if Settings().dark_style:
            try:
                import qdarkstyle
            except ImportError:
                Settings().dark_style = False
            else:
                qt_api = os.environ[QT_API]
                if qt_api in PYQT5_API:
                    qss = qdarkstyle.load_stylesheet_pyqt5()
                else:
                    qss = qdarkstyle.load_stylesheet(qt_api in PYSIDE_API)
                self.app.setStyleSheet(qss)
                return
        self.app.setStyleSheet('')

    def run(self):
        """
        Run the Qt main loop.
        """
        if Settings().fullscreen:
            self.win.showFullScreen()
        else:
            self.win.showMaximized()
        return self.app.exec_()

    @classmethod
    def init_env(cls):
        """
        Inits the environment
        :return:
        """
        s = Settings()
        if s.path_enabled:
            os.environ['PATH'] = s.path + os.pathsep + os.environ['PATH']
        else:
            try:
                os.environ['PATH'] = _original_env['PATH']
            except KeyError:
                pass
        if s.cob_config_dir_enabled:
            os.environ['COB_CONFIG_DIR'] = s.cob_config_dir
        else:
            try:
                os.environ['COB_CONFIG_DIR'] = _original_env['COB_CONFIG_DIR']
            except KeyError:
                if 'COB_CONFIG_DIR' in os.environ:
                    os.environ['COB_CONFIG_DIR'] = ''
        if s.cob_copy_dir_enabled:
            os.environ['COB_COPY_DIR'] = s.cob_copy_dir
        else:
            try:
                os.environ['COB_COPY_DIR'] = _original_env['COB_COPY_DIR']
            except KeyError:
                if 'COB_COPY_DIR' in os.environ:
                    os.environ['COB_COPY_DIR'] = ''
        if s.cob_include_path_enabled:
            os.environ['COB_INCLUDE_PATH'] = s.cob_include_path
        else:
            try:
                os.environ['COB_INCLUDE_PATH'] = _original_env[
                    'COB_INCLUDE_PATH']
            except KeyError:
                if 'COB_INCLUDE_PATH' in os.environ:
                    os.environ['COB_INCLUDE_PATH'] = ''
        if s.cob_lib_path_enabled:
            os.environ['COB_LIB_PATH'] = s.cob_lib_path
        else:
            try:
                os.environ['COB_LIB_PATH'] = _original_env['COB_LIB_PATH']
            except KeyError:
                if 'COB_LIB_PATH' in os.environ:
                    os.environ['COB_LIB_PATH'] = ''
        if system.darwin:
            Application._osx_init()

    @staticmethod
    def _osx_init():
        """
        Mac OSX specific initialisation, adds missing path to the PATH
        environment variable (see github issue #40).

        """
        #
        paths = [
            '/bin', '/sbin', '/usr/bin', '/usr/sbin', '/usr/local/bin',
            '/usr/local/sbin', '/opt/bin', '/opt/sbin', '/opt/local/bin',
            '/opt/local/sbin'
        ]
        os.environ['PATH'] = ':'.join(paths)

    def exit(self):
        """
        Closes all top level windows and quits the application (without
        prompting the user, if you need to prompt the user, use
        Application.file.quit())
        """
        self.app.closeAllWindows()
        self.close()

    def parse_args(self):
        parser = argparse.ArgumentParser(
            description='Simple and lightweight COBOL IDE.')
        parser.add_argument('files',
                            type=str,
                            nargs='*',
                            help='List of files to open, if any')
        parser.add_argument('--verbose',
                            dest='verbose',
                            action='store_true',
                            help='Verbose mode will enable debug and info '
                            'messages to be shown in the application log')
        return parser.parse_args()
Example #6
0
class Application(QtCore.QObject):
    """
    Sets up the Qt Application, the main window and the various controllers.

    The application class contains references to the main window user interface
    and to the various controllers so that they can collaborate each others.
    """
    _report_exception_requested = QtCore.pyqtSignal(object, str)

    def apply_mimetypes_preferences(self):
        for ext in Settings().all_extensions:
            mimetypes.add_type('text/x-cobol', ext)
            mimetypes.add_type('text/x-cobol', ext.upper())

    def __init__(self, parse_args=True):
        super().__init__()
        if system.darwin:
            Application._osx_init()
        self._reported_tracebacks = []
        self._old_except_hook = sys.excepthook
        sys.excepthook = self._except_hook
        self._report_exception_requested.connect(self._report_exception)
        if hasattr(sys, 'frozen') and sys.platform == 'win32':
            sys.stdout = open(
                os.path.join(system.get_cache_directory(), 'ocide_stdout.log'),
                'w')
            sys.stderr = open(
                os.path.join(system.get_cache_directory(), 'ocide_stderr.log'),
                'w')
        self.app = QtWidgets.QApplication(sys.argv)
        if parse_args and not system.darwin:
            args = self.parse_args()
            verbose = args.verbose
            files = args.files
        else:
            verbose = False
            files = []
        logger.setup_logging(__version__, debug=verbose or Settings().verbose)
        self.name = 'OpenCobolIDE'
        self.version = __version__
        self.title = '%s %s' % (self.name, self.version)

        self.apply_mimetypes_preferences()

        self.win = MainWindow()
        self.win.setWindowTitle(self.title)
        self.file = FileController(self)
        self.view = ViewController(self)
        self.home = HomeController(self)
        self.edit = EditController(self)
        self.cobol = CobolController(self)
        self.help = HelpController(self)

        self.view.show_perspective(Settings().perspective)
        self.view.show_home_page()

        self.update_app_style()

        try:
            check_compiler()
        except CompilerNotFound:
            msg = 'Failed to find a working GnuCOBOL compiler!\n' \
                "The IDE will continue to work but you won't be able to " \
                'compile...'
            if system.windows:
                msg += '\n\nTip: Ensure that there is no additional ' \
                    'installation of MinGW in %s:\MinGW' % sys.executable[0]
            QtWidgets.QMessageBox.warning(
                self.win, 'COBOL compiler not found or not working', msg)
        else:
            _logger().info('GnuCOBOL version: %s',
                           GnuCobolCompiler.get_version())
        # open specified files
        for f in files:
            self.file.open_file(f)

    def restart(self):
        """
        Restarts the IDE.
        """
        if hasattr(sys, 'frozen'):
            QtCore.QProcess.startDetached(sys.executable)
        else:
            QtCore.QProcess.startDetached(sys.executable, sys.argv)
        sys.exit(0)

    def close(self):
        self.view = None
        self.cobol = None
        self.edit = None
        self.file = None
        self.win = None
        self.home = None
        self.help = None

    def update_app_style(self):
        if Settings().dark_style:
            try:
                import qdarkstyle
            except ImportError:
                Settings().dark_style = False
            else:
                qt_api = os.environ[QT_API]
                if qt_api in PYQT5_API:
                    qss = qdarkstyle.load_stylesheet_pyqt5()
                else:
                    qss = qdarkstyle.load_stylesheet(qt_api in PYSIDE_API)
                self.app.setStyleSheet(qss)
                return
        self.app.setStyleSheet('')

    def run(self):
        """
        Run the Qt main loop.
        """
        if Settings().fullscreen:
            self.win.showFullScreen()
        else:
            self.win.showMaximized()
        return self.app.exec_()

    @staticmethod
    def _osx_init():
        """
        Mac OSX specific initialisation, adds missing path to the PATH
        environment variable (see github issue #40).

        """
        #
        paths = [
            '/bin', '/sbin', '/usr/bin', '/usr/sbin', '/usr/local/bin',
            '/usr/local/sbin', '/opt/bin', '/opt/sbin', '/opt/local/bin',
            '/opt/local/sbin'
        ]
        os.environ['PATH'] = ':'.join(paths)

    def exit(self):
        """
        Closes all top level windows and quits the application (without
        prompting the user, if you need to prompt the user, use
        Application.file.quit())
        """
        self.app.closeAllWindows()
        self.close()

    def parse_args(self):
        parser = argparse.ArgumentParser(
            description='Simple and lightweight COBOL IDE.')
        parser.add_argument('files',
                            type=str,
                            nargs='*',
                            help='List of files to open, if any')
        parser.add_argument('--verbose',
                            dest='verbose',
                            action='store_true',
                            help='Verbose mode will enable debug and info '
                            'messages to be shown in the application log')
        return parser.parse_args()

    def _except_hook(self, exc_type, exc_val, tb):
        tb = '\n'.join([
            ''.join(traceback.format_tb(tb)),
            '{0}: {1}'.format(exc_type.__name__, exc_val)
        ])
        # exception might come from another thread, use a signal
        # so that we can be sure we will show the bug report dialog from
        # the main gui thread.
        self._report_exception_requested.emit(exc_val, tb)

    def _report_exception(self, exc, tb):
        try:
            _logger().critical('unhandled exception:\n%s', tb)
            _tb = tb
            if isinstance(exc, UnicodeDecodeError):
                # This might be the same exception in the same file but at another position
                # in the stream
                _tb = tb.splitlines()[-4]
            if _tb in self._reported_tracebacks:
                return
            self._reported_tracebacks.append(_tb)
            title = '[Unhandled exception] %s' % exc.__class__.__name__
            description = 'An unhandled exception has occured:\n\n'\
                          '%s\n\nWould like to send a bug report to the ' \
                          'development team?' % tb
            answer = QtWidgets.QMessageBox.critical(
                self.win, title, description,
                QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
                QtWidgets.QMessageBox.Yes)
            if answer == QtWidgets.QMessageBox.Yes:
                description = '## Steps to reproduce\n\nPLEASE DESCRIBE '\
                    'THE CONTEXT OF THIS BUG AND THE STEPS TO REPRODUCE!\n\n'\
                    '## Traceback\n\n```\n%s\n```' % tb
                DlgReportBug.report_bug(self.win,
                                        title=title,
                                        description=description)

        except Exception:
            _logger().exception('exception in excepthook')