mirror of
				https://github.com/kovidgoyal/calibre.git
				synced 2025-11-04 03:27:00 -05:00 
			
		
		
		
	Linux: Use the system dark mode setting
This comes from the desktop settings portal implemented in KDE 5.24 and GNOME 42
This commit is contained in:
		
							parent
							
								
									8bf10b1056
								
							
						
					
					
						commit
						bc97485ff2
					
				@ -49,7 +49,7 @@ Environment variables
 | 
				
			|||||||
      the system theme -- beware of crashes and hangs.
 | 
					      the system theme -- beware of crashes and hangs.
 | 
				
			||||||
    * ``CALIBRE_SHOW_DEPRECATION_WARNINGS`` - causes calibre to print deprecation warnings to stdout. Useful for calibre developers.
 | 
					    * ``CALIBRE_SHOW_DEPRECATION_WARNINGS`` - causes calibre to print deprecation warnings to stdout. Useful for calibre developers.
 | 
				
			||||||
    * ``CALIBRE_NO_DEFAULT_PROGRAMS`` - prevent calibre from automatically registering the filetypes it is capable of handling with Windows.
 | 
					    * ``CALIBRE_NO_DEFAULT_PROGRAMS`` - prevent calibre from automatically registering the filetypes it is capable of handling with Windows.
 | 
				
			||||||
    * ``CALIBRE_USE_DARK_PALETTE`` - set it to ``1`` to have calibre use dark colors. Works on **Linux only**.
 | 
					    * ``CALIBRE_USE_DARK_PALETTE`` - set it to ``1`` to have calibre use dark colors and ``0`` for light colors. Works on **Linux only**.
 | 
				
			||||||
    * ``SYSFS_PATH`` - Use if sysfs is mounted somewhere other than /sys
 | 
					    * ``SYSFS_PATH`` - Use if sysfs is mounted somewhere other than /sys
 | 
				
			||||||
    * ``http_proxy``, ``https_proxy`` - used on Linux to specify an HTTP(S) proxy
 | 
					    * ``http_proxy``, ``https_proxy`` - used on Linux to specify an HTTP(S) proxy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,7 @@ from qt.core import (
 | 
				
			|||||||
    QFileIconProvider, QFileInfo, QFont, QFontDatabase, QFontInfo, QFontMetrics,
 | 
					    QFileIconProvider, QFileInfo, QFont, QFontDatabase, QFontInfo, QFontMetrics,
 | 
				
			||||||
    QGuiApplication, QIcon, QIODevice, QLocale, QNetworkProxyFactory, QObject,
 | 
					    QGuiApplication, QIcon, QIODevice, QLocale, QNetworkProxyFactory, QObject,
 | 
				
			||||||
    QPalette, QResource, QSettings, QSocketNotifier, QStringListModel, QStyle, Qt,
 | 
					    QPalette, QResource, QSettings, QSocketNotifier, QStringListModel, QStyle, Qt,
 | 
				
			||||||
    QThread, QTimer, QTranslator, QUrl, pyqtSignal
 | 
					    QThread, QTimer, QTranslator, QUrl, pyqtSignal, pyqtSlot
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
from threading import Lock, RLock
 | 
					from threading import Lock, RLock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -47,6 +47,8 @@ try:
 | 
				
			|||||||
    NO_URL_FORMATTING = QUrl.UrlFormattingOption.None_
 | 
					    NO_URL_FORMATTING = QUrl.UrlFormattingOption.None_
 | 
				
			||||||
except AttributeError:
 | 
					except AttributeError:
 | 
				
			||||||
    NO_URL_FORMATTING = getattr(QUrl, 'None')
 | 
					    NO_URL_FORMATTING = getattr(QUrl, 'None')
 | 
				
			||||||
 | 
					if islinux:
 | 
				
			||||||
 | 
					    from qt.dbus import QDBusConnection, QDBusMessage, QDBusVariant
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class IconResourceManager:
 | 
					class IconResourceManager:
 | 
				
			||||||
@ -1234,7 +1236,14 @@ class Application(QApplication):
 | 
				
			|||||||
            elif ismacos:
 | 
					            elif ismacos:
 | 
				
			||||||
                use_dark_palette = False
 | 
					                use_dark_palette = False
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                use_dark_palette = os.environ.get('CALIBRE_USE_DARK_PALETTE') == '1'
 | 
					                if 'CALIBRE_USE_DARK_PALETTE' in os.environ:
 | 
				
			||||||
 | 
					                    use_dark_palette = os.environ.get('CALIBRE_USE_DARK_PALETTE') == '1'
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    use_dark_palette = linux_is_system_dark_mode_enabled()
 | 
				
			||||||
 | 
					                    bus = QDBusConnection.sessionBus()
 | 
				
			||||||
 | 
					                    bus.connect(
 | 
				
			||||||
 | 
					                        'org.freedesktop.portal.Desktop', '/org/freedesktop/portal/desktop',
 | 
				
			||||||
 | 
					                        'org.freedesktop.portal.Settings', 'SettingChanged', 'ssv', self.linux_desktop_setting_changed)
 | 
				
			||||||
            if use_dark_palette:
 | 
					            if use_dark_palette:
 | 
				
			||||||
                self.set_dark_mode_palette()
 | 
					                self.set_dark_mode_palette()
 | 
				
			||||||
            elif self.original_palette_modified:
 | 
					            elif self.original_palette_modified:
 | 
				
			||||||
@ -1247,6 +1256,18 @@ class Application(QApplication):
 | 
				
			|||||||
            self.load_calibre_style()
 | 
					            self.load_calibre_style()
 | 
				
			||||||
        self.on_palette_change()
 | 
					        self.on_palette_change()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if islinux:
 | 
				
			||||||
 | 
					        @pyqtSlot(str, str, QDBusVariant)
 | 
				
			||||||
 | 
					        def linux_desktop_setting_changed(self, namespace, key, val):
 | 
				
			||||||
 | 
					            if (namespace, key) == ('org.freedesktop.appearance', 'color-scheme'):
 | 
				
			||||||
 | 
					                use_dark_palette = val.variant() == 1
 | 
				
			||||||
 | 
					                if use_dark_palette != bool(self.is_dark_theme):
 | 
				
			||||||
 | 
					                    if use_dark_palette:
 | 
				
			||||||
 | 
					                        self.set_dark_mode_palette()
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        self.set_palette(self.original_palette)
 | 
				
			||||||
 | 
					                self.on_palette_change()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def check_for_windows_palette_change(self):
 | 
					    def check_for_windows_palette_change(self):
 | 
				
			||||||
        use_dark_palette = bool(windows_is_system_dark_mode_enabled())
 | 
					        use_dark_palette = bool(windows_is_system_dark_mode_enabled())
 | 
				
			||||||
        if bool(self.is_dark_theme) != use_dark_palette:
 | 
					        if bool(self.is_dark_theme) != use_dark_palette:
 | 
				
			||||||
@ -1670,6 +1691,18 @@ def windows_is_system_dark_mode_enabled():
 | 
				
			|||||||
    return False
 | 
					    return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def linux_is_system_dark_mode_enabled():
 | 
				
			||||||
 | 
					    bus = QDBusConnection.sessionBus()
 | 
				
			||||||
 | 
					    m = QDBusMessage.createMethodCall(
 | 
				
			||||||
 | 
					        'org.freedesktop.portal.Desktop', '/org/freedesktop/portal/desktop',
 | 
				
			||||||
 | 
					        'org.freedesktop.portal.Settings', 'Read'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    m.setArguments(['org.freedesktop.appearance', 'color-scheme'])
 | 
				
			||||||
 | 
					    reply = bus.call(m, timeout=1000)
 | 
				
			||||||
 | 
					    a = reply.arguments()
 | 
				
			||||||
 | 
					    return len(a) and isinstance(a[0], int) and a[0] == 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def make_view_use_window_background(view):
 | 
					def make_view_use_window_background(view):
 | 
				
			||||||
    p = view.palette()
 | 
					    p = view.palette()
 | 
				
			||||||
    p.setColor(QPalette.ColorRole.Base, p.color(QPalette.ColorRole.Window))
 | 
					    p.setColor(QPalette.ColorRole.Base, p.color(QPalette.ColorRole.Window))
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
# autogenerated by __main__.py do not edit
 | 
					# autogenerated by __main__.py do not edit
 | 
				
			||||||
top_level_module_names=('QtCore', 'QtGui', 'QtWidgets', 'QtNetwork', 'QtSvg', 'QtPrintSupport', 'QtWebEngineCore', 'QtWebEngineWidgets')
 | 
					top_level_module_names=('QtCore', 'QtGui', 'QtWidgets', 'QtNetwork', 'QtSvg', 'QtPrintSupport', 'QtWebEngineCore', 'QtWebEngineWidgets', 'QtDBus')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def __getattr__(name):
 | 
					def __getattr__(name):
 | 
				
			||||||
 | 
				
			|||||||
@ -22,6 +22,9 @@ module_lists = {
 | 
				
			|||||||
        'QtWebEngineCore',
 | 
					        'QtWebEngineCore',
 | 
				
			||||||
        'QtWebEngineWidgets',
 | 
					        'QtWebEngineWidgets',
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
 | 
					    'dbus': (
 | 
				
			||||||
 | 
					        'QtDBus',
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -54,7 +57,7 @@ def scan(name):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
top_level_module_names = ()
 | 
					top_level_module_names = ()
 | 
				
			||||||
for name in ('core', 'webengine'):
 | 
					for name in ('core', 'webengine', 'dbus'):
 | 
				
			||||||
    top_level_module_names += module_lists[name]
 | 
					    top_level_module_names += module_lists[name]
 | 
				
			||||||
    scan(name)
 | 
					    scan(name)
 | 
				
			||||||
with open(f'{base}/__init__.py', 'w') as f:
 | 
					with open(f'{base}/__init__.py', 'w') as f:
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										14
									
								
								src/qt/dbus.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/qt/dbus.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					# vim:fileencoding=utf-8
 | 
				
			||||||
 | 
					# License: GPL v3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from .loader import dynamic_load
 | 
				
			||||||
 | 
					from .dbus_name_map import name_map, module_names
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					already_imported = {}
 | 
				
			||||||
 | 
					qt_modules = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def __getattr__(name):
 | 
				
			||||||
 | 
					    return dynamic_load(name, name_map, already_imported, qt_modules, module_names)
 | 
				
			||||||
							
								
								
									
										20
									
								
								src/qt/dbus.pyi
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/qt/dbus.pyi
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					# autogenerated by __main__.py do not edit
 | 
				
			||||||
 | 
					import PyQt6.QtDBus
 | 
				
			||||||
 | 
					QDBus = PyQt6.QtDBus.QDBus
 | 
				
			||||||
 | 
					QDBusAbstractAdaptor = PyQt6.QtDBus.QDBusAbstractAdaptor
 | 
				
			||||||
 | 
					QDBusAbstractInterface = PyQt6.QtDBus.QDBusAbstractInterface
 | 
				
			||||||
 | 
					QDBusArgument = PyQt6.QtDBus.QDBusArgument
 | 
				
			||||||
 | 
					QDBusConnection = PyQt6.QtDBus.QDBusConnection
 | 
				
			||||||
 | 
					QDBusConnectionInterface = PyQt6.QtDBus.QDBusConnectionInterface
 | 
				
			||||||
 | 
					QDBusError = PyQt6.QtDBus.QDBusError
 | 
				
			||||||
 | 
					QDBusInterface = PyQt6.QtDBus.QDBusInterface
 | 
				
			||||||
 | 
					QDBusMessage = PyQt6.QtDBus.QDBusMessage
 | 
				
			||||||
 | 
					QDBusObjectPath = PyQt6.QtDBus.QDBusObjectPath
 | 
				
			||||||
 | 
					QDBusPendingCall = PyQt6.QtDBus.QDBusPendingCall
 | 
				
			||||||
 | 
					QDBusPendingCallWatcher = PyQt6.QtDBus.QDBusPendingCallWatcher
 | 
				
			||||||
 | 
					QDBusPendingReply = PyQt6.QtDBus.QDBusPendingReply
 | 
				
			||||||
 | 
					QDBusReply = PyQt6.QtDBus.QDBusReply
 | 
				
			||||||
 | 
					QDBusServiceWatcher = PyQt6.QtDBus.QDBusServiceWatcher
 | 
				
			||||||
 | 
					QDBusSignature = PyQt6.QtDBus.QDBusSignature
 | 
				
			||||||
 | 
					QDBusUnixFileDescriptor = PyQt6.QtDBus.QDBusUnixFileDescriptor
 | 
				
			||||||
 | 
					QDBusVariant = PyQt6.QtDBus.QDBusVariant
 | 
				
			||||||
							
								
								
									
										22
									
								
								src/qt/dbus_name_map.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/qt/dbus_name_map.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					# autogenerated by __main__.py do not edit
 | 
				
			||||||
 | 
					name_map = {'QDBus': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QDBusAbstractAdaptor': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QDBusAbstractInterface': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QDBusArgument': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QDBusConnection': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QDBusConnectionInterface': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QDBusError': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QDBusInterface': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QDBusMessage': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QDBusObjectPath': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QDBusPendingCall': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QDBusPendingCallWatcher': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QDBusPendingReply': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QDBusReply': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QDBusServiceWatcher': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QDBusSignature': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QDBusUnixFileDescriptor': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QDBusVariant': 'PyQt6.QtDBus',
 | 
				
			||||||
 | 
					 'QtDBus': 'PyQt6.QtDBus'}
 | 
				
			||||||
 | 
					module_names = frozenset(('QtDBus',)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user