pare back dark mode support

Anki now solely relies on the night mode setting in the preferences
to decide whether to show in light or dark mode. Some users wanted
to run Anki in light mode while keeping the rest of their system dark,
and there were various display problems when dark mode was changed
after Anki started that couldn't be easily worked around.

NSRequiresAquaAppearance is set again, which means we can rely on
the interface appearing properly and not changing as the macOS theme
is changed.

Users who only use dark mode, and preferred the native look of widgets
in dark mode, can achieve the previous appearance by running the
following command in the terminal:

defaults write net.ankiweb.dtop NSRequiresAquaSystemAppearance -bool no

And the following in the debug console:

mw.pm.meta["dark_mode_widgets"] = True

This is hidden behind a debug console command because it requires the
user ensure their system is always set to the same light/dark mode
as Anki.
This commit is contained in:
Damien Elmes 2020-04-15 21:37:16 +10:00
parent b018dba073
commit 65cfcf9226
4 changed files with 14 additions and 33 deletions

View file

@ -10,7 +10,6 @@ import aqt
from anki.lang import _ from anki.lang import _
from aqt import AnkiQt from aqt import AnkiQt
from aqt.qt import * from aqt.qt import *
from aqt.theme import theme_manager
from aqt.utils import TR, askUser, openHelp, showInfo, showWarning, tr from aqt.utils import TR, askUser, openHelp, showInfo, showWarning, tr
@ -250,11 +249,7 @@ Not currently enabled; click the sync button in the main window to enable."""
self.form.pasteInvert.setChecked(self.prof.get("pasteInvert", False)) self.form.pasteInvert.setChecked(self.prof.get("pasteInvert", False))
self.form.showPlayButtons.setChecked(self.prof.get("showPlayButtons", True)) self.form.showPlayButtons.setChecked(self.prof.get("showPlayButtons", True))
self.form.nightMode.setChecked(self.mw.pm.night_mode()) self.form.nightMode.setChecked(self.mw.pm.night_mode())
if theme_manager.macos_dark_mode(): self.form.nightMode.setChecked(self.mw.pm.night_mode())
self.form.nightMode.setChecked(True)
self.form.nightMode.setText(tr(TR.PREFERENCES_DARK_MODE_ACTIVE))
else:
self.form.nightMode.setChecked(self.mw.pm.night_mode())
self.form.interrupt_audio.setChecked(self.mw.pm.interrupt_audio()) self.form.interrupt_audio.setChecked(self.mw.pm.interrupt_audio())
def updateOptions(self): def updateOptions(self):
@ -268,17 +263,9 @@ Not currently enabled; click the sync button in the main window to enable."""
restart_required = True restart_required = True
self.prof["showPlayButtons"] = self.form.showPlayButtons.isChecked() self.prof["showPlayButtons"] = self.form.showPlayButtons.isChecked()
if theme_manager.macos_dark_mode(): if self.mw.pm.night_mode() != self.form.nightMode.isChecked():
if not self.form.nightMode.isChecked(): self.mw.pm.set_night_mode(not self.mw.pm.night_mode())
# user is trying to turn it off, but it's forced restart_required = True
showInfo(
tr(TR.PREFERENCES_DARK_MODE_DISABLE), textFormat="rich",
)
openHelp("profileprefs")
else:
if self.mw.pm.night_mode() != self.form.nightMode.isChecked():
self.mw.pm.set_night_mode(not self.mw.pm.night_mode())
restart_required = True
self.mw.pm.set_interrupt_audio(self.form.interrupt_audio.isChecked()) self.mw.pm.set_interrupt_audio(self.form.interrupt_audio.isChecked())

View file

@ -496,6 +496,9 @@ create table if not exists profiles
def set_night_mode(self, on: bool) -> None: def set_night_mode(self, on: bool) -> None:
self.meta["night_mode"] = on self.meta["night_mode"] = on
def dark_mode_widgets(self) -> bool:
return self.meta.get("dark_mode_widgets", False)
# Profile-specific # Profile-specific
###################################################################### ######################################################################

View file

@ -3,13 +3,12 @@
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import platform import platform
import sys from typing import Dict
from typing import Dict, Optional
from anki.utils import isMac from anki.utils import isMac
from aqt import QApplication, gui_hooks, isWin from aqt import QApplication, gui_hooks, isWin
from aqt.colors import colors from aqt.colors import colors
from aqt.qt import QColor, QIcon, QPalette, QPixmap, QStyleFactory, Qt, qtminor from aqt.qt import QColor, QIcon, QPalette, QPixmap, QStyleFactory, Qt
class ThemeManager: class ThemeManager:
@ -17,25 +16,18 @@ class ThemeManager:
_icon_cache_light: Dict[str, QIcon] = {} _icon_cache_light: Dict[str, QIcon] = {}
_icon_cache_dark: Dict[str, QIcon] = {} _icon_cache_dark: Dict[str, QIcon] = {}
_icon_size = 128 _icon_size = 128
_macos_dark_mode_cached: Optional[bool] = None
def macos_dark_mode(self) -> bool: def macos_dark_mode(self) -> bool:
if not getattr(sys, "frozen", False): "True if the user has night mode on, and has forced native widgets."
return False
if not isMac: if not isMac:
return False return False
if qtminor < 13:
return False
if self._macos_dark_mode_cached is None:
import darkdetect # pylint: disable=import-error
# cache the value, as the interface gets messed up from aqt import mw
# if the value changes after starting Anki
self._macos_dark_mode_cached = darkdetect.isDark() is True return self._night_mode_preference and mw.pm.dark_mode_widgets()
return self._macos_dark_mode_cached
def get_night_mode(self) -> bool: def get_night_mode(self) -> bool:
return self.macos_dark_mode() or self._night_mode_preference return self._night_mode_preference
def set_night_mode(self, val: bool) -> None: def set_night_mode(self, val: bool) -> None:
self._night_mode_preference = val self._night_mode_preference = val

View file

@ -30,7 +30,6 @@ install_requires = [
"pyqt5>=5.9", "pyqt5>=5.9",
'psutil; sys.platform == "win32"', 'psutil; sys.platform == "win32"',
'pywin32; sys.platform == "win32"', 'pywin32; sys.platform == "win32"',
'darkdetect; sys.platform == "darwin"',
] ]