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')
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')
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')
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()
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()
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')