def openProfile(self, profile: str) -> None: if profile: if profile not in self.profiles(): QMessageBox.critical(None, tr.qt_misc_error(), tr.profiles_profile_does_not_exist()) sys.exit(1) try: self.load(profile) except TypeError as exc: raise Exception("Provided profile does not exist.") from exc
def msgHandler(category: Any, ctx: Any, msg: Any) -> None: if category == QtMsgType.QtDebugMsg: category = "debug" elif category == QtMsgType.QtInfoMsg: category = "info" elif category == QtMsgType.QtWarningMsg: category = "warning" elif category == QtMsgType.QtCriticalMsg: category = "critical" elif category == QtMsgType.QtDebugMsg: category = "debug" elif category == QtMsgType.QtFatalMsg: category = "fatal" else: category = "unknown" context = "" if ctx.file: context += f"{ctx.file}:" if ctx.line: context += f"{ctx.line}," if ctx.function: context += f"{ctx.function}" if context: context = f"'{context}'" if ("Failed to create OpenGL context" in msg # Based on the message Qt6 shows to the user; have not tested whether # we can actually capture this or not. or "Failed to initialize graphics backend" in msg): QMessageBox.critical( None, tr.qt_misc_error(), tr.qt_misc_error_loading_graphics_driver( mode=driver.value, context=context, ), ) pm.set_video_driver(driver.next()) return else: print(f"Qt {category}: {msg} {context}")
def msgHandler(category: Any, ctx: Any, msg: Any) -> None: if category == QtDebugMsg: category = "debug" elif category == QtInfoMsg: category = "info" elif category == QtWarningMsg: category = "warning" elif category == QtCriticalMsg: category = "critical" elif category == QtDebugMsg: category = "debug" elif category == QtFatalMsg: category = "fatal" elif category == QtSystemMsg: category = "system" else: category = "unknown" context = "" if ctx.file: context += f"{ctx.file}:" if ctx.line: context += f"{ctx.line}," if ctx.function: context += f"{ctx.function}" if context: context = f"'{context}'" if "Failed to create OpenGL context" in msg: QMessageBox.critical( None, tr.qt_misc_error(), tr.qt_misc_error_loading_graphics_driver( mode=driver.value, context=context, ), ) pm.set_video_driver(driver.next()) return else: print(f"Qt {category}: {msg} {context}")
def _run(argv: Optional[list[str]] = None, exec: bool = True) -> Optional[AnkiApp]: """Start AnkiQt application or reuse an existing instance if one exists. If the function is invoked with exec=False, the AnkiQt will not enter the main event loop - instead the application object will be returned. The 'exec' and 'argv' arguments will be useful for testing purposes. If no 'argv' is supplied then 'sys.argv' will be used. """ global mw global profiler if argv is None: argv = sys.argv # parse args opts, args = parseArgs(argv) if opts.version: print(f"Anki {appVersion}") return None elif opts.syncserver: from anki.syncserver import serve serve() return None if PROFILE_CODE: profiler = cProfile.Profile() profiler.enable() if (getattr(sys, "frozen", False) and os.getenv("QT_QPA_PLATFORM") == "wayland" and not os.getenv("ANKI_WAYLAND")): # users need to opt in to wayland support, given the issues it has print("Wayland support is disabled by default due to bugs.") print("You can force it on with an env var: ANKI_WAYLAND=1") os.environ["QT_QPA_PLATFORM"] = "xcb" # default to specified/system language before getting user's preference so that we can localize some more strings lang = anki.lang.get_def_lang(opts.lang) anki.lang.set_lang(lang[1]) # profile manager pm = None try: pm = ProfileManager(opts.base) pmLoadResult = pm.setupMeta() except: # will handle below traceback.print_exc() pm = None if pm: # gl workarounds setupGL(pm) # apply user-provided scale factor os.environ["QT_SCALE_FACTOR"] = str(pm.uiScale()) # opt in to full hidpi support? if not os.environ.get("ANKI_NOHIGHDPI") and qtmajor == 5: QCoreApplication.setAttribute( Qt.ApplicationAttribute.AA_EnableHighDpiScaling) # type: ignore QCoreApplication.setAttribute( Qt.ApplicationAttribute.AA_UseHighDpiPixmaps) # type: ignore os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "1" os.environ["QT_SCALE_FACTOR_ROUNDING_POLICY"] = "PassThrough" # Opt into software rendering. Useful for buggy systems. if os.environ.get("ANKI_SOFTWAREOPENGL"): QCoreApplication.setAttribute( Qt.ApplicationAttribute.AA_UseSoftwareOpenGL) if (isWin and qtmajor == 5 and (qtminor == 14 or (qtminor == 15 and qtpoint == 0)) and "QT_QPA_PLATFORM" not in os.environ): os.environ["QT_QPA_PLATFORM"] = "windows:altgr" # create the app QCoreApplication.setApplicationName("Anki") QGuiApplication.setDesktopFileName("anki.desktop") app = AnkiApp(argv) if app.secondInstance(): # we've signaled the primary instance, so we should close return None if not pm: QMessageBox.critical( None, tr.qt_misc_error(), tr.profiles_could_not_create_data_folder(), ) return None # disable icons on mac; this must be done before window created if isMac: app.setAttribute(Qt.ApplicationAttribute.AA_DontShowIconsInMenus) # disable help button in title bar on qt versions that support it if isWin and qtmajor == 5 and qtminor >= 10: QApplication.setAttribute( QApplication.Attribute. AA_DisableWindowContextHelpButton # type: ignore ) # proxy configured? from urllib.request import getproxies, proxy_bypass disable_proxies = False try: if "http" in getproxies(): # if it's not set up to bypass localhost, we'll # need to disable proxies in the webviews if not proxy_bypass("127.0.0.1"): disable_proxies = True except UnicodeDecodeError: # proxy_bypass can't handle unicode in hostnames; assume we need # to disable proxies disable_proxies = True if disable_proxies: print("webview proxy use disabled") proxy = QNetworkProxy() proxy.setType(QNetworkProxy.ProxyType.NoProxy) QNetworkProxy.setApplicationProxy(proxy) # we must have a usable temp dir try: tempfile.gettempdir() except: QMessageBox.critical( None, tr.qt_misc_error(), tr.qt_misc_no_temp_folder(), ) return None # make image resources available from aqt.utils import aqt_data_folder QDir.addSearchPath("icons", os.path.join(aqt_data_folder(), "qt", "icons")) if pmLoadResult.firstTime: pm.setDefaultLang(lang[0]) if pmLoadResult.loadError: QMessageBox.warning( None, tr.profiles_prefs_corrupt_title(), tr.profiles_prefs_file_is_corrupt(), ) if opts.profile: pm.openProfile(opts.profile) # i18n & backend backend = setupLangAndBackend(pm, app, opts.lang, pmLoadResult.firstTime) driver = pm.video_driver() if isLin and driver == VideoDriver.OpenGL: from aqt.utils import gfxDriverIsBroken if gfxDriverIsBroken(): pm.set_video_driver(driver.next()) QMessageBox.critical( None, tr.qt_misc_error(), tr.qt_misc_incompatible_video_driver(), ) sys.exit(1) # load the main window import aqt.main mw = aqt.main.AnkiQt(app, pm, backend, opts, args) if exec: app.exec() else: return app if PROFILE_CODE: write_profile_results() return None