qcanvas 1.2.0a0__py3-none-any.whl → 1.2.0a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of qcanvas might be problematic. Click here for more details.

qcanvas/run.py CHANGED
@@ -23,7 +23,7 @@
23
23
  # nuitka-project: --nofollow-import-to=yt_dlp.extractor.lazy_extractors
24
24
 
25
25
  import logging
26
- from logging import DEBUG, INFO, WARNING
26
+ from logging import INFO, WARNING
27
27
 
28
28
  import qcanvas.app_start
29
29
  from qcanvas.util import logs, paths
@@ -42,7 +42,6 @@ logs.set_levels(
42
42
  "qcanvas.ui": WARNING,
43
43
  "qcanvas_backend": INFO,
44
44
  "qcanvas.ui.main_ui.status_bar_progress_display": INFO,
45
- "qcanvas.util.themes": DEBUG,
46
45
  }
47
46
  )
48
47
 
@@ -5,12 +5,13 @@ from typing import *
5
5
  import qcanvas_backend.database.types as db
6
6
  from qcanvas_backend.net.resources.download.resource_manager import ResourceManager
7
7
  from qcanvas_backend.net.sync.sync_receipt import SyncReceipt, empty_receipt
8
- from qtpy.QtCore import Qt
8
+ from qtpy.QtCore import Qt, Slot
9
9
  from qtpy.QtGui import QIcon
10
10
  from qtpy.QtWidgets import *
11
11
 
12
12
  from qcanvas import icons
13
13
  from qcanvas.ui.course_viewer.course_viewer import CourseViewer
14
+ from qcanvas.util import themes
14
15
 
15
16
  _logger = logging.getLogger(__name__)
16
17
 
@@ -23,24 +24,35 @@ class _PlaceholderLogo(QLabel):
23
24
 
24
25
  def __init__(self):
25
26
  super().__init__()
26
- self._icon = QIcon(icons.logo_transparent_light)
27
+ self._light_icon = QIcon(icons.logo_transparent_light)
28
+ self._dark_icon = QIcon(icons.logo_transparent_dark)
27
29
  self._old_width = -1
28
30
  self._old_height = -1
29
31
  self.setAlignment(Qt.AlignmentFlag.AlignCenter)
30
32
  self.setSizePolicy(QSizePolicy.Policy.Ignored, QSizePolicy.Policy.Ignored)
33
+ themes.theme_changed().connect(self._theme_changed)
31
34
 
32
35
  def resizeEvent(self, event) -> None:
36
+ self._update_image()
37
+
38
+ @Slot()
39
+ def _theme_changed(self) -> None:
40
+ self._update_image(force=True)
41
+
42
+ def _update_image(self, force: bool = False) -> None:
33
43
  # Calculate the size of the logo as half of the width/height with a max size of 1000x1000
34
44
  width = min(floor(self.width() * 0.5), 500)
35
45
  height = min(floor(self.height() * 0.5), 500)
36
46
 
37
- if width == self._old_width or height == self._old_height:
38
- return
39
- else:
47
+ if force or (width != self._old_width and height != self._old_height):
40
48
  self._old_width = width
41
49
  self._old_height = height
50
+ else:
51
+ return
52
+
53
+ icon = self._dark_icon if themes.is_dark_mode() else self._light_icon
42
54
 
43
- self.setPixmap(self._icon.pixmap(width, height))
55
+ self.setPixmap(icon.pixmap(width, height))
44
56
 
45
57
 
46
58
  class CourseViewerContainer(QStackedWidget):
@@ -0,0 +1,2 @@
1
+ from ._theme_changed_event import theme_changed
2
+ from ._theme_changer import apply, default_theme, ensure_theme_is_valid, is_dark_mode
@@ -0,0 +1,38 @@
1
+ import logging
2
+
3
+ from qtpy.QtCore import QObject, Signal, Slot
4
+ from qtpy.QtGui import QGuiApplication, Qt
5
+
6
+ _logger = logging.getLogger(__name__)
7
+
8
+
9
+ def colour_scheme() -> Qt.ColorScheme:
10
+ return QGuiApplication.styleHints().colorScheme()
11
+
12
+
13
+ def is_dark_colour_scheme() -> bool:
14
+ return colour_scheme() == Qt.ColorScheme.Dark
15
+
16
+
17
+ class ColourSchemeChangeEvent(QObject):
18
+ theme_changed = Signal()
19
+
20
+ def __init__(self):
21
+ super().__init__(None)
22
+ self._last_theme = colour_scheme()
23
+ QGuiApplication.styleHints().colorSchemeChanged.connect(self._theme_changed)
24
+
25
+ @Slot(Qt.ColorScheme)
26
+ def _theme_changed(self, colour_scheme: Qt.ColorScheme) -> None:
27
+ # Ensure the signal isn't fired when there wasn't actually a change
28
+ if colour_scheme != self._last_theme:
29
+ self._last_theme = colour_scheme
30
+ self.theme_changed.emit()
31
+
32
+
33
+ _theme_changed_listener = ColourSchemeChangeEvent()
34
+
35
+
36
+ def colour_scheme_changed() -> Signal:
37
+ global _theme_changed_listener
38
+ return _theme_changed_listener.theme_changed
@@ -0,0 +1,10 @@
1
+ import logging
2
+ from enum import Enum
3
+
4
+ _logger = logging.getLogger(__name__)
5
+
6
+
7
+ class SelectedTheme(Enum):
8
+ AUTO = 0
9
+ NATIVE = 1
10
+ OVERRIDE = 2
@@ -0,0 +1,17 @@
1
+ import logging
2
+
3
+ from qtpy.QtCore import QObject, Signal
4
+
5
+ _logger = logging.getLogger(__name__)
6
+
7
+
8
+ class ThemeChangedEvent(QObject):
9
+ theme_changed = Signal()
10
+
11
+
12
+ theme_changed_event = ThemeChangedEvent(None)
13
+
14
+
15
+ def theme_changed() -> Signal:
16
+ global theme_changed_event
17
+ return theme_changed_event.theme_changed
@@ -0,0 +1,74 @@
1
+ import logging
2
+
3
+ import qdarktheme
4
+ from qtpy.QtCore import Slot
5
+ from qtpy.QtWidgets import QApplication, QStyleFactory
6
+
7
+ from qcanvas.util.themes._colour_scheme_helper import (
8
+ colour_scheme_changed,
9
+ is_dark_colour_scheme,
10
+ )
11
+ from qcanvas.util.themes._selected_theme import SelectedTheme
12
+ from qcanvas.util.themes._theme_changed_event import theme_changed
13
+
14
+ _logger = logging.getLogger(__name__)
15
+
16
+ default_theme = "auto"
17
+ _is_dark_mode: bool | None = None
18
+ _selected_theme: SelectedTheme | None = None
19
+
20
+
21
+ def apply(theme: str) -> None:
22
+ global _is_dark_mode, _selected_theme
23
+
24
+ theme = ensure_theme_is_valid(theme)
25
+ was_dark_mode = _is_dark_mode
26
+
27
+ if theme != "native":
28
+ if theme == "auto":
29
+ _is_dark_mode = is_dark_colour_scheme()
30
+ _selected_theme = SelectedTheme.AUTO
31
+ selected_colour_scheme = "dark" if _is_dark_mode else "light"
32
+ else:
33
+ _is_dark_mode = theme == "dark"
34
+ _selected_theme = SelectedTheme.OVERRIDE
35
+ selected_colour_scheme = theme
36
+
37
+ qdarktheme.setup_theme(
38
+ selected_colour_scheme,
39
+ custom_colors={"primary": "e02424"},
40
+ )
41
+
42
+ QApplication.setStyle(QStyleFactory.create("Fusion"))
43
+ else:
44
+ _is_dark_mode = is_dark_colour_scheme()
45
+ _selected_theme = SelectedTheme.NATIVE
46
+
47
+ if was_dark_mode != _is_dark_mode:
48
+ theme_changed().emit()
49
+
50
+
51
+ def is_dark_mode() -> bool:
52
+ return _is_dark_mode
53
+
54
+
55
+ def ensure_theme_is_valid(theme: str) -> str:
56
+ if theme not in ["auto", "light", "dark", "native"]:
57
+ return default_theme
58
+ else:
59
+ return theme
60
+
61
+
62
+ @Slot()
63
+ def _scheme_changed():
64
+ global _selected_theme, _is_dark_mode
65
+
66
+ if _selected_theme == SelectedTheme.AUTO:
67
+ apply("auto")
68
+ elif _selected_theme == SelectedTheme.NATIVE:
69
+ # noinspection PyTestUnpassedFixture
70
+ _is_dark_mode = is_dark_colour_scheme()
71
+ theme_changed().emit()
72
+
73
+
74
+ colour_scheme_changed().connect(_scheme_changed)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: qcanvas
3
- Version: 1.2.0a0
3
+ Version: 1.2.0a1
4
4
  Summary: QCanvas is a desktop client for Canvas LMS.
5
5
  Author: QCanvas
6
6
  Author-email: QCanvas@noreply.codeberg.org
@@ -3,17 +3,18 @@ qcanvas/app_start/__init__.py,sha256=r16bg9Otw8Sy6MYLmIt5Nu-oSwyYP8Y2kzMtbmeF6m0
3
3
  qcanvas/backend_connectors/__init__.py,sha256=Wj8cmxQng3SSlmlXJyzHaPmvxbkauwsxINckPb7WuHc,108
4
4
  qcanvas/backend_connectors/frontend_resource_manager.py,sha256=87oszxCle0Y9AUAHH3wn_7oilY45ddMET-4EnpTtjn0,1322
5
5
  qcanvas/backend_connectors/qcanvas_task_master.py,sha256=CTPBvf_9w-livscKNspnd98mNvFLYTYHef0RQSUkfFc,742
6
- qcanvas/icons/__init__.py,sha256=UxZ4PLlkLirumWPU8OreBYXjnelexE6W8VK5u9UWXKo,302
6
+ qcanvas/icons/__init__.py,sha256=HQJzW9BXiWqj8yRHRvevlSWZ-TLB7vUbVlwuQKgX_Lk,356
7
7
  qcanvas/icons/file-download-failed.svg,sha256=lhDf8ul__T2ByRcd5KZicNtUVl4BdSqeZ3yOR6DvCLk,1091
8
8
  qcanvas/icons/file-downloaded.svg,sha256=fWDcSy0PwQX3LZwaEVJLE3fUVg7q1TO3n44svyUyb64,1091
9
9
  qcanvas/icons/file-not-downloaded.svg,sha256=7zl_Gmx2IHZrugFYAUjBCSwmfXM0pvlshj8GhewxY5Q,1091
10
10
  qcanvas/icons/file-unknown.svg,sha256=9xlN244HJX3zM_MqdMTnNbKlqLjOFgCx3ZdM4Wc4zC0,1729
11
- qcanvas/icons/icons.qrc,sha256=h181m7XWs1Xs_yhuT8UNj-LBO5hdcpCGbU0uoeXUT7A,328
11
+ qcanvas/icons/icons.qrc,sha256=tI5HDO3a9eMWhkrEfdQrnIkEAH7L4-kpDu-t-wstE10,375
12
+ qcanvas/icons/logo-transparent-dark.svg,sha256=1bVg8AK9FepOvWTcu_zDLX2eZ1inYuAMBwZRi252-5o,18660
12
13
  qcanvas/icons/logo-transparent-light.svg,sha256=DsNOFWHGAVCZ-ue-pf1iatQ1t_IBmnyxs3FNw-UUukg,18647
13
14
  qcanvas/icons/main_icon.svg,sha256=st2sfA8HIETmoacJ2Oq84iJzfnNHH-T03ijB-J419_s,16104
14
- qcanvas/icons/rc_icons.py,sha256=VI1sBDuXbHHzolgtjDVi2flt4SjB9DKqt-vlQuRvXvY,31692
15
+ qcanvas/icons/rc_icons.py,sha256=AlCluQJETsrxGHG4lBrZnDpJY5oVt9OzTj0qIODkYSE,44764
15
16
  qcanvas/icons/sync.svg,sha256=J-7_KnFbQL3uh-RrTy0_wSJUVW4Cc6ZSTacld6ULv1w,2829
16
- qcanvas/run.py,sha256=XW4NQEZtBICRqLQUOCzzbFspYtBHBJhkHJKdB25hpVQ,1726
17
+ qcanvas/run.py,sha256=tP5bplaPa_Z8DaKqP59bwYaIEccW5B18xoyXgKJsrf8,1681
17
18
  qcanvas/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
19
  qcanvas/ui/course_viewer/__init__.py,sha256=XkoFnh4ULw3_i-GDsOlueEWido0PkoDcN9_EX6-nkXY,76
19
20
  qcanvas/ui/course_viewer/content_tree.py,sha256=QS0mcyxLDdXt27TBzdCTYu2fuchPO-j6z6VPJT6rhkA,4478
@@ -37,7 +38,7 @@ qcanvas/ui/course_viewer/tabs/page_tab/page_tree.py,sha256=ffM-IFdNPBdTggmJCnseu
37
38
  qcanvas/ui/course_viewer/tabs/resource_rich_browser.py,sha256=dTRsJO_xeo72vsX0FrT1XHfr9VlFjnM9woeFxVg0dDw,6649
38
39
  qcanvas/ui/course_viewer/tabs/util.py,sha256=Cg8FmPbkiTepV9IlTZQSWtcUaovv66iAD4_BUYJjIAY,344
39
40
  qcanvas/ui/main_ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
- qcanvas/ui/main_ui/course_viewer_container.py,sha256=yXZyVfqyKZWkmsYVqIzNHWfShTib40Rs60BpLzCRM0c,2849
41
+ qcanvas/ui/main_ui/course_viewer_container.py,sha256=EJo0QnlD-Rz04Yy_k1md4YjYTGOwg1dxdsPMPHtCVFA,3277
41
42
  qcanvas/ui/main_ui/options/__init__.py,sha256=SlfWUzk6_E5uM9GIV-y9BVeKMwqn3pRx_xWhMyb1dfI,54
42
43
  qcanvas/ui/main_ui/options/auto_download_resources_option.py,sha256=W9BleGh6egfN9d9awnjEAAFq6_6DyXyD-rIopkofVDw,1284
43
44
  qcanvas/ui/main_ui/options/quick_sync_option.py,sha256=qEfmtLllO32ejc-bydCvFRjal5RUlk2HtC5Ld4mT7ss,753
@@ -66,10 +67,14 @@ qcanvas/util/settings/__init__.py,sha256=ivc8bczhQdEJsWse6fc81Xyz0i2YX57pL4UubM3
66
67
  qcanvas/util/settings/_client_settings.py,sha256=HyUpXoc7TinOviEd-eCo8g8Fbw8TqGAH2KfCkgPr9N0,1413
67
68
  qcanvas/util/settings/_mapped_setting.py,sha256=Z6635FfDll9cCLfSkVg-unsDLvUWuKT5MmxJEiUkd2k,1823
68
69
  qcanvas/util/settings/_ui_settings.py,sha256=zlWMjpntuqm7ZN3aBEROGrXc4bhtKOfWijmiGkdt1UA,804
69
- qcanvas/util/themes.py,sha256=Lw33zWTkD2jSuntYZYWPi8rxLfj5VLv-_PjtjgkPsEQ,796
70
+ qcanvas/util/themes/__init__.py,sha256=Ng-Rii7cFKrhSoE03J5tSYeaMY4UebFubKCBsWxouYM,134
71
+ qcanvas/util/themes/_colour_scheme_helper.py,sha256=QTrQ5c9AduBJMUuXp8sG-WPmYU82cF1tXjGDKhpI10w,1063
72
+ qcanvas/util/themes/_selected_theme.py,sha256=w1CXvMuLM8wKDgANOhcvNnlEXDyjdgnWO0TtA3vGomY,150
73
+ qcanvas/util/themes/_theme_changed_event.py,sha256=dIu1857h2ytSqmcRb2CABro3Gc0s9bm5DHdT23jyuk8,317
74
+ qcanvas/util/themes/_theme_changer.py,sha256=ybMgKT2sL_orvH0OYXPOlA5w6hociMjMQbbTJgNw1Us,1993
70
75
  qcanvas/util/ui_tools.py,sha256=bSM1xrmZPn847YEbXAC9VIAv--8hMLMWrsEMWGA5p3E,916
71
76
  qcanvas/util/url_checker.py,sha256=gaV_KZZsG5bfJaGBv9jbHJjq0rVxIH55HRtucT6Qkx8,144
72
- qcanvas-1.2.0a0.dist-info/METADATA,sha256=LgyN2I1DImidV4JuLlK53bshAe6BvW4T1GbbGVu0W74,1794
73
- qcanvas-1.2.0a0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
74
- qcanvas-1.2.0a0.dist-info/entry_points.txt,sha256=46VbnhQ9w2CYdfhYcPfWgjXYHjsKshu0asQ1B_sAMac,44
75
- qcanvas-1.2.0a0.dist-info/RECORD,,
77
+ qcanvas-1.2.0a1.dist-info/METADATA,sha256=DvxP1JLD7MNLfjfpxZ6hOOiEKzV88TS4WiUwbrtER3o,1794
78
+ qcanvas-1.2.0a1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
79
+ qcanvas-1.2.0a1.dist-info/entry_points.txt,sha256=46VbnhQ9w2CYdfhYcPfWgjXYHjsKshu0asQ1B_sAMac,44
80
+ qcanvas-1.2.0a1.dist-info/RECORD,,
qcanvas/util/themes.py DELETED
@@ -1,33 +0,0 @@
1
- import logging
2
-
3
- import darkdetect
4
- import qdarktheme
5
- from qtpy.QtGui import QGuiApplication
6
- from qtpy.QtWidgets import QApplication, QStyleFactory
7
-
8
- _logger = logging.getLogger(__name__)
9
-
10
- default_theme = "auto"
11
-
12
-
13
- def ensure_theme_is_valid(theme: str) -> str:
14
- if theme not in ["auto", "light", "dark", "native"]:
15
- return default_theme
16
- else:
17
- return theme
18
-
19
-
20
- def apply(theme: str) -> None:
21
- theme = ensure_theme_is_valid(theme)
22
-
23
- if theme != "native":
24
-
25
- qdarktheme.setup_theme(
26
- theme,
27
- custom_colors={"primary": "e02424"},
28
- )
29
-
30
- QApplication.setStyle(QStyleFactory.create("Fusion"))
31
-
32
- _logger.debug("darkdetect says: %s", darkdetect.theme())
33
- _logger.debug("qt says: %s", QGuiApplication.styleHints().colorScheme())