示例#1
0
    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
示例#2
0
    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