qcanvas 1.2.1__py3-none-any.whl → 2.0.0__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.

Files changed (130) hide show
  1. qcanvas/__init__.py +54 -0
  2. qcanvas/app.py +93 -0
  3. qcanvas/backend_connectors/frontend_resource_manager.py +13 -5
  4. qcanvas/backend_connectors/qcanvas_task_master.py +2 -2
  5. qcanvas/icons/__init__.py +5 -5
  6. qcanvas/icons/_icon_type.py +1 -1
  7. qcanvas/icons/icons.qrc +47 -43
  8. qcanvas/icons/rc_icons.py +1298 -1197
  9. qcanvas/settings/__init__.py +6 -0
  10. qcanvas/{util/settings → settings}/_client_settings.py +4 -4
  11. qcanvas/settings/_course_settings.py +54 -0
  12. qcanvas/{util/settings → settings}/_mapped_setting.py +2 -5
  13. qcanvas/{util/settings → settings}/_ui_settings.py +5 -5
  14. qcanvas/theme.py +101 -0
  15. qcanvas/ui/course_viewer/content_tree.py +9 -12
  16. qcanvas/ui/course_viewer/course_tree/_course_icon_generator.py +3 -3
  17. qcanvas/ui/course_viewer/course_tree/course_tree.py +9 -8
  18. qcanvas/ui/course_viewer/course_viewer.py +35 -43
  19. qcanvas/ui/course_viewer/tabs/assignment_tab/assignment_tab.py +107 -29
  20. qcanvas/ui/course_viewer/tabs/assignment_tab/assignment_tree.py +4 -4
  21. qcanvas/ui/course_viewer/tabs/constants.py +1 -0
  22. qcanvas/ui/course_viewer/tabs/content_tab.py +33 -39
  23. qcanvas/ui/course_viewer/tabs/file_tab/file_tab.py +4 -4
  24. qcanvas/ui/course_viewer/tabs/file_tab/file_tree.py +7 -10
  25. qcanvas/ui/course_viewer/tabs/file_tab/pages_file_tree.py +6 -7
  26. qcanvas/ui/course_viewer/tabs/mail_tab/mail_tab.py +50 -27
  27. qcanvas/ui/course_viewer/tabs/mail_tab/mail_tree.py +7 -8
  28. qcanvas/ui/course_viewer/tabs/page_tab/page_tab.py +3 -3
  29. qcanvas/ui/course_viewer/tabs/page_tab/page_tree.py +5 -5
  30. qcanvas/ui/course_viewer/tabs/resource_rich_browser.py +15 -21
  31. qcanvas/ui/course_viewer/tree_widget_data_item.py +1 -1
  32. qcanvas/ui/memory_tree/_tree_memory.py +45 -42
  33. qcanvas/ui/memory_tree/memory_tree_widget.py +22 -18
  34. qcanvas/ui/memory_tree/memory_tree_widget_item.py +3 -3
  35. qcanvas/ui/qcanvas_window/__init__.py +1 -0
  36. qcanvas/ui/{main_ui → qcanvas_window}/course_viewer_container.py +10 -10
  37. qcanvas/ui/{main_ui → qcanvas_window}/options/auto_download_resources_option.py +5 -5
  38. qcanvas/ui/{main_ui → qcanvas_window}/options/quick_sync_option.py +7 -6
  39. qcanvas/ui/{main_ui → qcanvas_window}/options/sync_on_start_option.py +7 -6
  40. qcanvas/ui/{main_ui → qcanvas_window}/options/theme_selection_menu.py +10 -10
  41. qcanvas/ui/{main_ui → qcanvas_window}/qcanvas_window.py +42 -36
  42. qcanvas/ui/{main_ui → qcanvas_window}/status_bar_progress_display.py +5 -6
  43. qcanvas/ui/qml_components/AttachmentsList.ui.qml +15 -0
  44. qcanvas/ui/qml_components/AttachmentsListDelegate.qml +77 -0
  45. qcanvas/ui/qml_components/AttachmentsListModel.qml +19 -0
  46. qcanvas/ui/qml_components/AttachmentsPane.qml +12 -0
  47. qcanvas/ui/qml_components/CommentsList.ui.qml +15 -0
  48. qcanvas/ui/qml_components/CommentsListDelegate.ui.qml +118 -0
  49. qcanvas/ui/qml_components/CommentsListModel.qml +56 -0
  50. qcanvas/ui/qml_components/CommentsPane.qml +12 -0
  51. qcanvas/ui/qml_components/DarkTheme.qml +12 -0
  52. qcanvas/ui/qml_components/DecoratedText.ui.qml +44 -0
  53. qcanvas/ui/qml_components/LightTheme.qml +11 -0
  54. qcanvas/ui/qml_components/Spacer.ui.qml +7 -0
  55. qcanvas/ui/qml_components/ThemedRectangle.qml +37 -0
  56. qcanvas/ui/qml_components/__init__.py +3 -0
  57. qcanvas/ui/qml_components/attachments_pane.py +72 -0
  58. qcanvas/ui/qml_components/comments_pane.py +85 -0
  59. qcanvas/ui/qml_components/qml_bridge_types.py +95 -0
  60. qcanvas/ui/qml_components/qml_pane.py +22 -0
  61. qcanvas/ui/setup/setup_checker.py +1 -1
  62. qcanvas/ui/setup/setup_dialog.py +27 -10
  63. qcanvas/util/auto_downloader.py +9 -7
  64. qcanvas/util/basic_fonts.py +2 -2
  65. qcanvas/util/context_dict.py +12 -0
  66. qcanvas/util/file_icons.py +11 -19
  67. qcanvas/util/layouts.py +5 -7
  68. qcanvas/util/paths.py +17 -6
  69. qcanvas/util/qurl_util.py +1 -1
  70. qcanvas/util/ui_tools.py +118 -8
  71. qcanvas/util/url_checker.py +1 -1
  72. {qcanvas-1.2.1.dist-info → qcanvas-2.0.0.dist-info}/METADATA +13 -11
  73. qcanvas-2.0.0.dist-info/RECORD +91 -0
  74. {qcanvas-1.2.1.dist-info → qcanvas-2.0.0.dist-info}/WHEEL +1 -1
  75. qcanvas-2.0.0.dist-info/entry_points.txt +3 -0
  76. qcanvas/app_start/__init__.py +0 -59
  77. qcanvas/icons/_update_icons.py +0 -89
  78. qcanvas/icons/dark/actions/exit.svg +0 -3
  79. qcanvas/icons/dark/actions/mark_all_read.svg +0 -3
  80. qcanvas/icons/dark/actions/open_downloads.svg +0 -3
  81. qcanvas/icons/dark/actions/quick_login.svg +0 -3
  82. qcanvas/icons/dark/actions/sync.svg +0 -3
  83. qcanvas/icons/dark/branding/logo_transparent.svg +0 -303
  84. qcanvas/icons/dark/options/auto_download.svg +0 -3
  85. qcanvas/icons/dark/options/theme.svg +0 -3
  86. qcanvas/icons/dark/tabs/assignments.svg +0 -3
  87. qcanvas/icons/dark/tabs/mail.svg +0 -3
  88. qcanvas/icons/dark/tabs/pages.svg +0 -3
  89. qcanvas/icons/dark/tree_items/assignment.svg +0 -3
  90. qcanvas/icons/dark/tree_items/mail.svg +0 -3
  91. qcanvas/icons/dark/tree_items/module.svg +0 -3
  92. qcanvas/icons/dark/tree_items/page.svg +0 -3
  93. qcanvas/icons/light/actions/exit.svg +0 -3
  94. qcanvas/icons/light/actions/mark_all_read.svg +0 -3
  95. qcanvas/icons/light/actions/open_downloads.svg +0 -3
  96. qcanvas/icons/light/actions/quick_login.svg +0 -3
  97. qcanvas/icons/light/actions/sync.svg +0 -3
  98. qcanvas/icons/light/branding/logo_transparent.svg +0 -304
  99. qcanvas/icons/light/options/auto_download.svg +0 -3
  100. qcanvas/icons/light/options/ignore_old.svg +0 -3
  101. qcanvas/icons/light/options/include_videos.svg +0 -3
  102. qcanvas/icons/light/options/theme.svg +0 -3
  103. qcanvas/icons/light/tabs/assignments.svg +0 -3
  104. qcanvas/icons/light/tabs/mail.svg +0 -3
  105. qcanvas/icons/light/tabs/pages.svg +0 -3
  106. qcanvas/icons/light/tree_items/assignment.svg +0 -3
  107. qcanvas/icons/light/tree_items/mail.svg +0 -3
  108. qcanvas/icons/light/tree_items/module.svg +0 -3
  109. qcanvas/icons/light/tree_items/page.svg +0 -3
  110. qcanvas/icons/universal/branding/main_icon.svg +0 -325
  111. qcanvas/icons/universal/downloads/download_failed.svg +0 -23
  112. qcanvas/icons/universal/downloads/downloaded.svg +0 -23
  113. qcanvas/icons/universal/downloads/not_downloaded.svg +0 -23
  114. qcanvas/icons/universal/downloads/unknown.svg +0 -6
  115. qcanvas/icons/universal/tabs/assignments_new_content.svg +0 -3
  116. qcanvas/icons/universal/tabs/mail_new_content.svg +0 -3
  117. qcanvas/icons/universal/tabs/pages_new_content.svg +0 -3
  118. qcanvas/icons/universal/tree_items/semester.svg +0 -108
  119. qcanvas/run.py +0 -54
  120. qcanvas/ui/course_viewer/tabs/util.py +0 -11
  121. qcanvas/ui/main_ui/__init__.py +0 -0
  122. qcanvas/util/settings/__init__.py +0 -9
  123. qcanvas/util/themes/__init__.py +0 -2
  124. qcanvas/util/themes/_colour_scheme_helper.py +0 -38
  125. qcanvas/util/themes/_selected_theme.py +0 -10
  126. qcanvas/util/themes/_theme_changed_event.py +0 -17
  127. qcanvas/util/themes/_theme_changer.py +0 -86
  128. qcanvas-1.2.1.dist-info/RECORD +0 -118
  129. qcanvas-1.2.1.dist-info/entry_points.txt +0 -3
  130. /qcanvas/ui/{main_ui → qcanvas_window}/options/__init__.py +0 -0
qcanvas/__init__.py CHANGED
@@ -0,0 +1,54 @@
1
+ # nuitka-project: --enable-plugin=pyside6
2
+ # nuitka-project: --windows-icon-from-ico=./deploy/windows/qcanvas.ico
3
+ # nuitka-project: --windows-console-mode=attach
4
+ # nuitka-project: --linux-icon=deploy/appimage/qcanvas.svg
5
+ # nuitka-project: --standalone
6
+ # nuitka-project: --include-module=yt_dlp
7
+
8
+ # Anti-bloat
9
+
10
+ ##########################################################
11
+ # nuitka-project: --include-package=aiosqlite
12
+ # nuitka-project: --nofollow-import-to=aiosqlite.tests.*
13
+ ##########################################################
14
+ # nuitka-project: --nofollow-import-to=rich
15
+ ##########################################################
16
+ # nuitka-project: --nofollow-import-to=sqlalchemy.dialects.mssql
17
+ # nuitka-project: --nofollow-import-to=sqlalchemy.dialects.postgresql
18
+ # nuitka-project: --nofollow-import-to=sqlalchemy.dialects.oracle
19
+ # nuitka-project: --nofollow-import-to=sqlalchemy.dialects.mysql
20
+ ##########################################################
21
+ # nuitka-project: --nofollow-import-to=rich
22
+ ##########################################################
23
+ # nuitka-project: --nofollow-import-to=yt_dlp.extractor.lazy_extractors
24
+
25
+ import logging
26
+ from logging import INFO, WARNING
27
+
28
+ import qcanvas.app as app
29
+ from qcanvas.util import logs, paths
30
+
31
+
32
+ def main():
33
+ app.launch()
34
+
35
+
36
+ if __name__ == "__main__":
37
+ paths.data_storage().mkdir(parents=True, exist_ok=True)
38
+
39
+ logging.basicConfig(
40
+ filemode="w",
41
+ filename=paths.data_storage() / "debug.log",
42
+ level="WARN",
43
+ )
44
+
45
+ logs.set_levels(
46
+ {
47
+ "qcanvas": INFO,
48
+ "qcanvas.ui": WARNING,
49
+ "libqcanvas": INFO,
50
+ "qcanvas.ui.main_ui.status_bar_progress_display": INFO,
51
+ }
52
+ )
53
+
54
+ main()
qcanvas/app.py ADDED
@@ -0,0 +1,93 @@
1
+ import asyncio
2
+ import logging
3
+ import sys
4
+
5
+ from libqcanvas.qcanvas import QCanvas
6
+ from PySide6.QtCore import QObject, Signal, Qt
7
+ from PySide6.QtGui import QGuiApplication
8
+ from PySide6.QtWidgets import QApplication
9
+ from qasync import QEventLoop, asyncSlot
10
+
11
+ import qcanvas.backend_connectors.qcanvas_task_master as task_master
12
+ from qcanvas.backend_connectors import FrontendResourceManager
13
+ from qcanvas.ui.qcanvas_window import QCanvasWindow
14
+ from qcanvas.ui.setup import SetupDialog, setup_checker
15
+ from qcanvas.util import paths, runtime
16
+ from qcanvas.theme import app_theme
17
+ import qcanvas.settings as settings
18
+
19
+ _logger = logging.getLogger(__name__)
20
+ app = QApplication(sys.argv)
21
+
22
+
23
+ # I couldn't figure out a reliable way of getting the event loop started.
24
+ # This just uses a signal with an async slot to run some async functions and then shows the main window
25
+ class _MainStarter(QObject):
26
+ _starting = Signal()
27
+
28
+ def __init__(self):
29
+ super().__init__()
30
+ self._starting.connect(self._start, Qt.ConnectionType.SingleShotConnection)
31
+
32
+ def start(self):
33
+ self._starting.emit()
34
+
35
+ @asyncSlot()
36
+ async def _start(self):
37
+ _qcanvas = await self._setup_database()
38
+
39
+ _main_window = QCanvasWindow(_qcanvas)
40
+ _main_window.show()
41
+ self.setParent(_main_window)
42
+
43
+ async def _setup_database(self) -> QCanvas[FrontendResourceManager]:
44
+ _qcanvas = QCanvas[FrontendResourceManager](
45
+ canvas_config=settings.client.canvas_config,
46
+ panopto_config=settings.client.panopto_config,
47
+ storage_path=paths.data_storage(),
48
+ resource_manager_class=FrontendResourceManager,
49
+ )
50
+
51
+ await _qcanvas.database.upgrade()
52
+ await _qcanvas.init()
53
+
54
+ return _qcanvas
55
+
56
+
57
+ def run_setup():
58
+ event_loop = QEventLoop(app)
59
+ asyncio.set_event_loop(event_loop)
60
+
61
+ app_close_event = asyncio.Event()
62
+ app.aboutToQuit.connect(app_close_event.set, Qt.ConnectionType.SingleShotConnection)
63
+
64
+ setup_window = SetupDialog()
65
+ setup_window.show()
66
+
67
+ with event_loop:
68
+ event_loop.run_until_complete(app_close_event.wait())
69
+
70
+
71
+ def launch():
72
+ if runtime.is_running_as_flatpak:
73
+ QGuiApplication.setDesktopFileName("io.github.qcanvas.QCanvasApp")
74
+
75
+ app.setApplicationName("QCanvas")
76
+
77
+ task_master.register()
78
+ app_theme.theme = settings.ui.theme
79
+
80
+ if setup_checker.needs_setup():
81
+ run_setup()
82
+
83
+ event_loop = QEventLoop(app)
84
+ asyncio.set_event_loop(event_loop)
85
+
86
+ app_close_event = asyncio.Event()
87
+ app.aboutToQuit.connect(app_close_event.set, Qt.ConnectionType.SingleShotConnection)
88
+
89
+ _main = _MainStarter()
90
+ _main.start()
91
+
92
+ with event_loop:
93
+ event_loop.run_until_complete(app_close_event.wait())
@@ -2,11 +2,14 @@ import logging
2
2
  from abc import ABCMeta
3
3
  from pathlib import Path
4
4
 
5
- import qcanvas_backend.database.types as db
6
- from qcanvas_backend.database import QCanvasDatabase
7
- from qcanvas_backend.net.resources.download.resource_manager import ResourceManager
8
- from qcanvas_backend.net.resources.extracting.extractors import Extractors
9
- from qtpy.QtCore import QObject, Signal
5
+ from PySide6.QtGui import QDesktopServices
6
+ from libqcanvas import db
7
+ from libqcanvas.database import QCanvasDatabase
8
+ from libqcanvas.net.resources.download.resource_manager import ResourceManager
9
+ from libqcanvas.net.resources.extracting.extractors import Extractors
10
+ from PySide6.QtCore import QObject, Signal
11
+
12
+ from qcanvas.util.qurl_util import file_url
10
13
 
11
14
  _logger = logging.getLogger(__name__)
12
15
 
@@ -29,6 +32,11 @@ class FrontendResourceManager(QObject, ResourceManager, metaclass=_Meta):
29
32
  database=database, download_dest=download_dest, extractors=extractors
30
33
  )
31
34
 
35
+ async def download_and_open(self, resource: db.Resource) -> None:
36
+ await self.download(resource)
37
+ resource_path = file_url(self.resource_download_location(resource))
38
+ QDesktopServices.openUrl(resource_path)
39
+
32
40
  def on_download_progress(
33
41
  self, resource: db.Resource, current: int, total: int
34
42
  ) -> None:
@@ -1,8 +1,8 @@
1
1
  import logging
2
2
  from abc import ABCMeta
3
3
 
4
- from qcanvas_backend.task_master import TaskID, TaskMaster, set_global_task_master
5
- from qtpy.QtCore import QObject, Signal
4
+ from libqcanvas.task_master import TaskID, TaskMaster, set_global_task_master
5
+ from PySide6.QtCore import QObject, Signal
6
6
 
7
7
  _logger = logging.getLogger(__name__)
8
8
 
qcanvas/icons/__init__.py CHANGED
@@ -1,9 +1,8 @@
1
- from qtpy.QtGui import QIcon
2
-
3
- from ._icon_type import ThemeIcon, UniversalIcon
4
1
  from .rc_icons import (
5
- qt_resource_data as _, # Without this, icon data will not be loaded
6
- )
2
+ qt_resource_data as _,
3
+ ) # Without this, icon data will not be loaded
4
+ from ._icon_type import UniversalIcon, ThemeIcon
5
+ from PySide6.QtGui import QIcon
7
6
 
8
7
 
9
8
  # noinspection PyPep8Naming
@@ -26,6 +25,7 @@ class options:
26
25
  auto_download = QIcon.fromTheme("options/auto_download")
27
26
  ignore_old = QIcon.fromTheme("options/ignore_old")
28
27
  include_videos = QIcon.fromTheme("options/include_videos")
28
+ sync_on_start = QIcon.fromTheme("options/sync_on_start")
29
29
  theme = QIcon.fromTheme("options/theme")
30
30
 
31
31
 
@@ -1,7 +1,7 @@
1
1
  # Unused
2
2
  import logging
3
3
 
4
- from qtpy.QtGui import QIcon
4
+ from PySide6.QtGui import QIcon
5
5
 
6
6
  _logger = logging.getLogger(__name__)
7
7
 
qcanvas/icons/icons.qrc CHANGED
@@ -1,46 +1,50 @@
1
1
  <!DOCTYPE RCC>
2
2
  <RCC version="1.0">
3
- <qresource prefix="icons/">
4
- <file>dark/actions/exit.svg</file>
5
- <file>dark/actions/mark_all_read.svg</file>
6
- <file>dark/actions/open_downloads.svg</file>
7
- <file>dark/actions/quick_login.svg</file>
8
- <file>dark/actions/sync.svg</file>
9
- <file>dark/branding/logo_transparent.svg</file>
10
- <file>dark/options/auto_download.svg</file>
11
- <file>dark/options/theme.svg</file>
12
- <file>dark/tabs/assignments.svg</file>
13
- <file>dark/tabs/mail.svg</file>
14
- <file>dark/tabs/pages.svg</file>
15
- <file>dark/tree_items/assignment.svg</file>
16
- <file>dark/tree_items/mail.svg</file>
17
- <file>dark/tree_items/module.svg</file>
18
- <file>dark/tree_items/page.svg</file>
19
- <file>light/actions/exit.svg</file>
20
- <file>light/actions/mark_all_read.svg</file>
21
- <file>light/actions/open_downloads.svg</file>
22
- <file>light/actions/quick_login.svg</file>
23
- <file>light/actions/sync.svg</file>
24
- <file>light/branding/logo_transparent.svg</file>
25
- <file>light/options/auto_download.svg</file>
26
- <file>light/options/ignore_old.svg</file>
27
- <file>light/options/include_videos.svg</file>
28
- <file>light/options/theme.svg</file>
29
- <file>light/tabs/assignments.svg</file>
30
- <file>light/tabs/mail.svg</file>
31
- <file>light/tabs/pages.svg</file>
32
- <file>light/tree_items/assignment.svg</file>
33
- <file>light/tree_items/mail.svg</file>
34
- <file>light/tree_items/module.svg</file>
35
- <file>light/tree_items/page.svg</file>
36
- <file>universal/branding/main_icon.svg</file>
37
- <file>universal/downloads/download_failed.svg</file>
38
- <file>universal/downloads/downloaded.svg</file>
39
- <file>universal/downloads/not_downloaded.svg</file>
40
- <file>universal/downloads/unknown.svg</file>
41
- <file>universal/tabs/assignments_new_content.svg</file>
42
- <file>universal/tabs/mail_new_content.svg</file>
43
- <file>universal/tabs/pages_new_content.svg</file>
44
- <file>universal/tree_items/semester.svg</file>
45
- </qresource>
3
+ <qresource prefix="icons/">
4
+ <file>dark/actions/exit.svg</file>
5
+ <file>dark/actions/mark_all_read.svg</file>
6
+ <file>dark/actions/open_downloads.svg</file>
7
+ <file>dark/actions/quick_login.svg</file>
8
+ <file>dark/actions/sync.svg</file>
9
+ <file>dark/branding/logo_transparent.svg</file>
10
+ <file>dark/options/auto_download.svg</file>
11
+ <file>dark/options/ignore_old.svg</file>
12
+ <file>dark/options/include_videos.svg</file>
13
+ <file>dark/options/sync_on_start.svg</file>
14
+ <file>dark/options/theme.svg</file>
15
+ <file>dark/tabs/assignments.svg</file>
16
+ <file>dark/tabs/mail.svg</file>
17
+ <file>dark/tabs/pages.svg</file>
18
+ <file>dark/tree_items/assignment.svg</file>
19
+ <file>dark/tree_items/mail.svg</file>
20
+ <file>dark/tree_items/module.svg</file>
21
+ <file>dark/tree_items/page.svg</file>
22
+ <file>light/actions/exit.svg</file>
23
+ <file>light/actions/mark_all_read.svg</file>
24
+ <file>light/actions/open_downloads.svg</file>
25
+ <file>light/actions/quick_login.svg</file>
26
+ <file>light/actions/sync.svg</file>
27
+ <file>light/branding/logo_transparent.svg</file>
28
+ <file>light/options/auto_download.svg</file>
29
+ <file>light/options/ignore_old.svg</file>
30
+ <file>light/options/include_videos.svg</file>
31
+ <file>light/options/sync_on_start.svg</file>
32
+ <file>light/options/theme.svg</file>
33
+ <file>light/tabs/assignments.svg</file>
34
+ <file>light/tabs/mail.svg</file>
35
+ <file>light/tabs/pages.svg</file>
36
+ <file>light/tree_items/assignment.svg</file>
37
+ <file>light/tree_items/mail.svg</file>
38
+ <file>light/tree_items/module.svg</file>
39
+ <file>light/tree_items/page.svg</file>
40
+ <file>universal/branding/main_icon.svg</file>
41
+ <file>universal/downloads/download_failed.svg</file>
42
+ <file>universal/downloads/downloaded.svg</file>
43
+ <file>universal/downloads/not_downloaded.svg</file>
44
+ <file>universal/downloads/unknown.svg</file>
45
+ <file>universal/tabs/assignments_new_content.svg</file>
46
+ <file>universal/tabs/mail_new_content.svg</file>
47
+ <file>universal/tabs/pages_new_content.svg</file>
48
+ <file>universal/tree_items/semester.svg</file>
49
+ </qresource>
46
50
  </RCC>