def _pre_and_post_app_setup(self): ''' Call this before instantiating the QApplication object. It sets up some platform-specific miscellany that need to happen before the QApplication is constructed. A function is returned. This function *must* be called after the QApplication is constructed. ''' callables = [] def call_callables(): for func in callables: func() ret = call_callables if hasattr(QGuiApplication, 'setDesktopFileName'): QGuiApplication.setDesktopFileName('electron-cash.desktop') if self.windows_qt_use_freetype: # Use FreeType for font rendering on Windows. This fixes rendering # of the Schnorr sigil and allows us to load the Noto Color Emoji # font if needed. os.environ['QT_QPA_PLATFORM'] = 'windows:fontengine=freetype' QCoreApplication.setAttribute(Qt.AA_X11InitThreads) if hasattr(Qt, "AA_ShareOpenGLContexts"): QCoreApplication.setAttribute(Qt.AA_ShareOpenGLContexts) if sys.platform not in ('darwin', ) and hasattr( Qt, "AA_EnableHighDpiScaling"): # The below only applies to non-macOS. On macOS this setting is # never used (because it is implicitly auto-negotiated by the OS # in a differernt way). # # qt_disable_highdpi will be set to None by default, or True if # specified on command-line. The command-line override is intended # to supporess high-dpi mode just for this run for testing. # # The more permanent setting is qt_enable_highdpi which is the GUI # preferences option, so we don't enable highdpi if it's explicitly # set to False in the GUI. # # The default on Linux, Windows, etc is to enable high dpi disable_scaling = self.config.get('qt_disable_highdpi', False) enable_scaling = self.config.get('qt_enable_highdpi', True) if not disable_scaling and enable_scaling: QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling) if hasattr(Qt, "AA_UseHighDpiPixmaps"): QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps) # macOS Mojave "font rendering looks terrible on PyQt5.11" workaround. # See: https://old.reddit.com/r/apple/comments/9leavs/fix_mojave_font_rendering_issues_on_a_perapp_basis/ # This affects PyQt 5.11 (which is what we ship in the macOS El Capitan # .dmg). We apply the workaround and also warn the user to not use # the El Capitan compatibility .dmg. if sys.platform in ('darwin', ) and self.qt_version() < (5, 12): # macOS hacks. On Mojave with PyQt <5.12 the font rendering is terrible. # As a workaround we need to temporarily set this 'defaults' keys # which we immediately disable after the QApplication is started. try: ver = tuple(int(a) for a in platform.mac_ver()[0].split('.')) except (TypeError, ValueError): self.print_error("WARNING: Cannot parse platform.mac_ver", f"'{platform.mac_ver()[0]}'") ver = None if ver and ver >= (10, 14): from electroncash.utils import macos self.print_error( "Mojave+ with PyQt<5.12 detected; applying CGFontRenderingFontSmoothingDisabled workaround..." ) bundle = macos.get_bundle_identifier() os.system( f'defaults write {bundle} CGFontRenderingFontSmoothingDisabled -bool NO' ) def undo_hack(): os.system( f'defaults delete {bundle} CGFontRenderingFontSmoothingDisabled' ) self.print_error( "Mojave+ font rendering workaround applied.") #msg = _("Mojave or newer system detected, however you are running the " # "El Capitan compatibility release of Electron Cash. " # "Font and graphics rendering may be affected." # "\n\nPlease obtain the latest non-compatibility version " # "of Electron Cash for MacOS.") #QMessageBox.warning(None, _("Warning"), msg) # this works even if app is not exec_() yet. callables.append(undo_hack) return ret
def _pre_and_post_app_setup(self): """ Call this before instantiating the QApplication object. It sets up some platform-specific miscellany that need to happen before the QApplication is constructed. A function is returned. This function *must* be called after the QApplication is constructed. """ callables = [] def call_callables(): for func in callables: func() ret = call_callables if hasattr(QGuiApplication, 'setDesktopFileName'): QGuiApplication.setDesktopFileName('electron-cash.desktop') if self.windows_qt_use_freetype: # Use FreeType for font rendering on Windows. This fixes rendering # of the Schnorr sigil and allows us to load the Noto Color Emoji # font if needed. os.environ['QT_QPA_PLATFORM'] = 'windows:fontengine=freetype' QCoreApplication.setAttribute(Qt.AA_X11InitThreads) if hasattr(Qt, "AA_ShareOpenGLContexts"): QCoreApplication.setAttribute(Qt.AA_ShareOpenGLContexts) if sys.platform not in ('darwin',) and hasattr(Qt, "AA_EnableHighDpiScaling"): # The below only applies to non-macOS. On macOS this setting is # never used (because it is implicitly auto-negotiated by the OS # in a differernt way). # # qt_disable_highdpi will be set to None by default, or True if # specified on command-line. The command-line override is intended # to supporess high-dpi mode just for this run for testing. # # The more permanent setting is qt_enable_highdpi which is the GUI # preferences option, so we don't enable highdpi if it's explicitly # set to False in the GUI. # # The default on Linux, Windows, etc is to enable high dpi disable_scaling = self.config.get('qt_disable_highdpi', False) enable_scaling = self.config.get('qt_enable_highdpi', True) if not disable_scaling and enable_scaling: QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling) if hasattr(Qt, "AA_UseHighDpiPixmaps"): QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps) # Set mac_ver to the appropriate macOS version e.g.: (10,15,1) for Catalina, etc or None if not macOS mac_ver = None if sys.platform in ('darwin',): try: mac_ver = tuple(int(a) for a in platform.mac_ver()[0].split('.')) self.print_error("macOS version:", mac_ver) except (TypeError, ValueError) as e: self.print_error("WARNING: Cannot parse platform.mac_ver:", repr(e)) # macOS Mojave "font rendering looks terrible on PyQt5.11" workaround. # See: https://old.reddit.com/r/apple/comments/9leavs/fix_mojave_font_rendering_issues_on_a_perapp_basis/ # This affects PyQt 5.11 (which is what we ship in the macOS El Capitan # .dmg). We apply the workaround and also warn the user to not use # the El Capitan compatibility .dmg. if mac_ver and mac_ver >= (10, 14) and self.qt_version() < (5, 12): # macOS hacks. On Mojave with PyQt <5.12 the font rendering is terrible. # As a workaround we need to temporarily set this 'defaults' keys # which we immediately disable after the QApplication is started. from electroncash.utils import macos self.print_error("Mojave+ with PyQt<5.12 detected; applying CGFontRenderingFontSmoothingDisabled workaround...") bundle = macos.get_bundle_identifier() os.system(f'defaults write {bundle} CGFontRenderingFontSmoothingDisabled -bool NO') def undo_hack(): os.system(f'defaults delete {bundle} CGFontRenderingFontSmoothingDisabled') self.print_error("Mojave+ font rendering workaround applied.") callables.append(undo_hack) # macOS Big Sur workaround for Qt>=5.13.2 sometimes not working at all # See: https://bugreports.qt.io/browse/QTBUG-87014 # See also: https://stackoverflow.com/questions/64818879/is-there-any-solution-regarding-to-pyqt-library-doesnt-work-in-mac-os-big-sur if mac_ver and mac_ver >= (10, 16) and self.qt_version() >= (5, 13, 2) and self.qt_version() < (5, 15, 2): # Setting this env var causes Qt to use some other macOS API that always works on Big Sur os.environ['QT_MAC_WANTS_LAYER'] = '1' self.print_error(f"macOS Big Sur Qt workaround applied") def setup_layout_direction(): """Sets the app layout direction depending on language. To be called after self.app is created successfully. Note this *MUST* be called after set_language has been called.""" assert i18n.set_language_called > 0 lc = i18n.language.info().get('language') lc = '' if not isinstance(lc, str) else lc lc = lc.split('_')[0] layout_direction = Qt.LeftToRight blurb = "left-to-right" if lc in {'ar', 'fa', 'he', 'ps', 'ug', 'ur'}: # Right-to-left languages layout_direction = Qt.RightToLeft blurb = "right-to-left" self.print_error("Setting layout direction:", blurb) self.app.setLayoutDirection(layout_direction) # callable will be called after self.app is set-up successfully callables.append(setup_layout_direction) return ret