qcanvas 1.0.7__tar.gz → 1.0.9.dev0__tar.gz
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-1.0.7 → qcanvas-1.0.9.dev0}/PKG-INFO +3 -2
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/pyproject.toml +6 -3
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/icons/file-download-failed.svg +5 -5
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/icons/file-downloaded.svg +5 -5
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/icons/file-not-downloaded.svg +5 -5
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/icons/file-unknown.svg +5 -5
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/run.py +2 -2
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/content_tree.py +10 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/course_tree.py +0 -4
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/tabs/assignment_tab/assignment_tab.py +0 -10
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/tabs/assignment_tab/assignment_tree.py +0 -8
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/tabs/content_tab.py +12 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/tabs/mail_tab/mail_tab.py +0 -9
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/tabs/mail_tab/mail_tree.py +0 -7
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/tabs/page_tab/page_tab.py +0 -10
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/tabs/page_tab/page_tree.py +0 -8
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/main_ui/status_bar_progress_display.py +5 -5
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/setup/setup_dialog.py +21 -11
- qcanvas-1.0.9.dev0/qcanvas/util/url_checker.py +9 -0
- qcanvas-1.0.7/qcanvas/util/url_checker.py +0 -13
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/README.md +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/__init__.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/app_start/__init__.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/backend_connectors/__init__.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/backend_connectors/frontend_resource_manager.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/backend_connectors/qcanvas_task_master.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/icons/__init__.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/icons/icons.qrc +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/icons/main_icon.svg +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/icons/rc_icons.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/icons/sync.svg +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/__init__.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/__init__.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/course_viewer.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/tabs/__init__.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/tabs/assignment_tab/__init__.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/tabs/mail_tab/__init__.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/tabs/page_tab/__init__.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/tabs/resource_rich_browser.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/tabs/util.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/main_ui/__init__.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/main_ui/course_viewer_container.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/main_ui/options/__init__.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/main_ui/options/quick_sync_option.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/main_ui/options/sync_on_start_option.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/main_ui/options/theme_selection_menu.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/main_ui/qcanvas_window.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/memory_tree/__init__.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/memory_tree/_tree_memory.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/memory_tree/memory_tree_widget.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/memory_tree/memory_tree_widget_item.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/setup/__init__.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/setup/setup_checker.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/util/__init__.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/util/basic_fonts.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/util/fe_resource_manager.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/util/html_cleaner.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/util/layouts.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/util/logs.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/util/paths.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/util/qurl_util.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/util/settings/__init__.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/util/settings/_client_settings.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/util/settings/_mapped_setting.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/util/settings/_ui_settings.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/util/themes.py +0 -0
- {qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/util/ui_tools.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: qcanvas
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.9.dev0
|
|
4
4
|
Summary: QCanvas is a desktop client for Canvas LMS.
|
|
5
5
|
Author: QCanvas
|
|
6
6
|
Author-email: QCanvas@noreply.codeberg.org
|
|
@@ -15,9 +15,10 @@ Requires-Dist: platformdirs (>=4.2.2,<5.0.0)
|
|
|
15
15
|
Requires-Dist: pyqtdarktheme-fork (>=2.3.2,<3.0.0)
|
|
16
16
|
Requires-Dist: qasync (>=0.27.1,<0.28.0)
|
|
17
17
|
Requires-Dist: qcanvas-api-clients (>=0.2.2,<0.3.0)
|
|
18
|
-
Requires-Dist: qcanvas-backend (==0.1.
|
|
18
|
+
Requires-Dist: qcanvas-backend (==0.1.10a5)
|
|
19
19
|
Requires-Dist: qtpy (>=2.4.1,<3.0.0)
|
|
20
20
|
Requires-Dist: sqlalchemy (>=2.0.31,<3.0.0)
|
|
21
|
+
Requires-Dist: validators (>=0.33.0,<0.34.0)
|
|
21
22
|
Description-Content-Type: text/markdown
|
|
22
23
|
|
|
23
24
|
# QCanvas
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "qcanvas"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.9.dev0"
|
|
4
4
|
description = "QCanvas is a desktop client for Canvas LMS."
|
|
5
5
|
authors = ["QCanvas <QCanvas@noreply.codeberg.org>"]
|
|
6
6
|
readme = "README.md"
|
|
7
7
|
exclude = [
|
|
8
|
-
"images"
|
|
8
|
+
"images",
|
|
9
|
+
"flatpak",
|
|
10
|
+
"appimage",
|
|
9
11
|
]
|
|
10
12
|
|
|
11
13
|
[tool.poetry.scripts]
|
|
@@ -14,7 +16,7 @@ qcanvas = "qcanvas.run:main"
|
|
|
14
16
|
[tool.poetry.dependencies]
|
|
15
17
|
python = ">=3.11,<3.13"
|
|
16
18
|
qcanvas-api-clients = "^0.2.2"
|
|
17
|
-
qcanvas-backend = "0.1.
|
|
19
|
+
qcanvas-backend = "0.1.10a5"
|
|
18
20
|
asynctaskpool = "^0.2.1"
|
|
19
21
|
sqlalchemy = "^2.0.31"
|
|
20
22
|
qtpy = "^2.4.1"
|
|
@@ -23,6 +25,7 @@ pyqtdarktheme-fork = "^2.3.2"
|
|
|
23
25
|
qasync = "^0.27.1"
|
|
24
26
|
lightdb = "^2.0"
|
|
25
27
|
platformdirs = "^4.2.2"
|
|
28
|
+
validators = "^0.33.0"
|
|
26
29
|
|
|
27
30
|
[tool.poetry.group.flatpak-exclude.dependencies]
|
|
28
31
|
pyside6 = "^6.7.2"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
3
|
-
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
|
4
|
-
<title>file-times</title>
|
|
5
|
-
<path d="M26.731 9.902c-0.005-0.035-0.011-0.066-0.019-0.095l0.001 0.005c-0.031-0.134-0.094-0.249-0.182-0.342l0 0-8-8c-0.092-0.087-0.207-0.15-0.335-0.181l-0.005-0.001c-0.027-0.008-0.059-0.014-0.092-0.019l-0.003-0c-0.026-0.007-0.059-0.014-0.092-0.019l-0.004-0h-12c-0.414 0-0.75 0.336-0.75 0.75v0 28c0 0.414 0.336 0.75 0.75 0.75h20c0.414-0 0.75-0.336 0.75-0.75v0-20c-0.005-0.038-0.012-0.071-0.020-0.103l0.001 0.005zM24.189 9.25h-5.439v-5.439zM6.75 29.25v-26.5h10.5v7.25c0 0.414 0.336 0.75 0.75 0.75h7.25v18.5zM20.066 15.935c-0.136-0.136-0.324-0.22-0.531-0.22s-0.395 0.084-0.531 0.22v0l-3.004 3.004-3.005-3.004c-0.136-0.141-0.327-0.228-0.538-0.228-0.414 0-0.75 0.336-0.75 0.75 0 0.211 0.087 0.402 0.228 0.538l3.004 3.005-3.004 3.004c-0.136 0.136-0.22 0.324-0.22 0.531 0 0.415 0.336 0.751 0.751 0.751 0.207 0 0.395-0.084 0.53-0.219v0l3.005-3.005 3.004 3.005c0.136 0.136 0.324 0.22 0.531 0.22 0.415 0 0.751-0.336 0.751-0.751 0-0.207-0.084-0.395-0.22-0.531l-3.005-3.004 3.005-3.005c0.135-0.136 0.218-0.323 0.218-0.53s-0.083-0.394-0.218-0.53l0 0z"></path>
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
3
|
+
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
|
4
|
+
<title>file-times</title>
|
|
5
|
+
<path d="M26.731 9.902c-0.005-0.035-0.011-0.066-0.019-0.095l0.001 0.005c-0.031-0.134-0.094-0.249-0.182-0.342l0 0-8-8c-0.092-0.087-0.207-0.15-0.335-0.181l-0.005-0.001c-0.027-0.008-0.059-0.014-0.092-0.019l-0.003-0c-0.026-0.007-0.059-0.014-0.092-0.019l-0.004-0h-12c-0.414 0-0.75 0.336-0.75 0.75v0 28c0 0.414 0.336 0.75 0.75 0.75h20c0.414-0 0.75-0.336 0.75-0.75v0-20c-0.005-0.038-0.012-0.071-0.020-0.103l0.001 0.005zM24.189 9.25h-5.439v-5.439zM6.75 29.25v-26.5h10.5v7.25c0 0.414 0.336 0.75 0.75 0.75h7.25v18.5zM20.066 15.935c-0.136-0.136-0.324-0.22-0.531-0.22s-0.395 0.084-0.531 0.22v0l-3.004 3.004-3.005-3.004c-0.136-0.141-0.327-0.228-0.538-0.228-0.414 0-0.75 0.336-0.75 0.75 0 0.211 0.087 0.402 0.228 0.538l3.004 3.005-3.004 3.004c-0.136 0.136-0.22 0.324-0.22 0.531 0 0.415 0.336 0.751 0.751 0.751 0.207 0 0.395-0.084 0.53-0.219v0l3.005-3.005 3.004 3.005c0.136 0.136 0.324 0.22 0.531 0.22 0.415 0 0.751-0.336 0.751-0.751 0-0.207-0.084-0.395-0.22-0.531l-3.005-3.004 3.005-3.005c0.135-0.136 0.218-0.323 0.218-0.53s-0.083-0.394-0.218-0.53l0 0z"></path>
|
|
6
6
|
</svg>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
3
|
-
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
|
4
|
-
<title>file</title>
|
|
5
|
-
<path d="M26.731 9.902c-0.005-0.035-0.011-0.066-0.019-0.095l0.001 0.005c-0.031-0.134-0.094-0.249-0.182-0.342l0 0-8-8c-0.092-0.087-0.207-0.15-0.335-0.181l-0.005-0.001c-0.027-0.008-0.059-0.014-0.092-0.019l-0.003-0c-0.026-0.007-0.059-0.014-0.092-0.019l-0.004-0h-12c-0.414 0-0.75 0.336-0.75 0.75v0 28c0 0.414 0.336 0.75 0.75 0.75h20c0.414-0 0.75-0.336 0.75-0.75v0-20c-0.005-0.038-0.012-0.071-0.020-0.103l0.001 0.005zM24.189 9.25h-5.439v-5.439zM6.75 29.25v-26.5h10.5v7.25c0 0.414 0.336 0.75 0.75 0.75h7.25v18.5z"></path>
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
3
|
+
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
|
4
|
+
<title>file</title>
|
|
5
|
+
<path d="M26.731 9.902c-0.005-0.035-0.011-0.066-0.019-0.095l0.001 0.005c-0.031-0.134-0.094-0.249-0.182-0.342l0 0-8-8c-0.092-0.087-0.207-0.15-0.335-0.181l-0.005-0.001c-0.027-0.008-0.059-0.014-0.092-0.019l-0.003-0c-0.026-0.007-0.059-0.014-0.092-0.019l-0.004-0h-12c-0.414 0-0.75 0.336-0.75 0.75v0 28c0 0.414 0.336 0.75 0.75 0.75h20c0.414-0 0.75-0.336 0.75-0.75v0-20c-0.005-0.038-0.012-0.071-0.020-0.103l0.001 0.005zM24.189 9.25h-5.439v-5.439zM6.75 29.25v-26.5h10.5v7.25c0 0.414 0.336 0.75 0.75 0.75h7.25v18.5z"></path>
|
|
6
6
|
</svg>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
3
|
-
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
|
4
|
-
<title>file-arrow-down</title>
|
|
5
|
-
<path d="M26.731 9.902c-0.005-0.035-0.011-0.066-0.019-0.095l0.001 0.005c-0.031-0.134-0.094-0.249-0.182-0.342l0 0-8-8c-0.092-0.087-0.207-0.15-0.335-0.181l-0.005-0.001c-0.027-0.008-0.059-0.014-0.092-0.019l-0.003-0c-0.026-0.007-0.059-0.014-0.092-0.019l-0.004-0h-12c-0.414 0-0.75 0.336-0.75 0.75v0 28c0 0.414 0.336 0.75 0.75 0.75h20c0.414-0 0.75-0.336 0.75-0.75v0-20c-0.005-0.038-0.012-0.071-0.020-0.103l0.001 0.005zM24.189 9.25h-5.439v-5.439zM6.75 29.25v-26.5h10.5v7.25c0 0.414 0.336 0.75 0.75 0.75h7.25v18.5zM20.469 20.91l-3.719 3.721v-10.676c0-0.414-0.336-0.75-0.75-0.75s-0.75 0.336-0.75 0.75v0 10.675l-3.72-3.72c-0.136-0.134-0.322-0.218-0.528-0.218-0.415 0-0.751 0.336-0.751 0.751 0 0.207 0.083 0.394 0.219 0.529l5 5c0.026 0.026 0.065 0.017 0.093 0.038 0.052 0.040 0.088 0.098 0.15 0.124 0.085 0.035 0.184 0.056 0.287 0.057h0c0 0 0 0 0 0 0.207 0 0.394-0.084 0.53-0.219l5.001-5c0.136-0.136 0.22-0.324 0.22-0.531 0-0.415-0.336-0.751-0.751-0.751-0.207 0-0.395 0.084-0.531 0.22v0z"></path>
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
3
|
+
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
|
4
|
+
<title>file-arrow-down</title>
|
|
5
|
+
<path d="M26.731 9.902c-0.005-0.035-0.011-0.066-0.019-0.095l0.001 0.005c-0.031-0.134-0.094-0.249-0.182-0.342l0 0-8-8c-0.092-0.087-0.207-0.15-0.335-0.181l-0.005-0.001c-0.027-0.008-0.059-0.014-0.092-0.019l-0.003-0c-0.026-0.007-0.059-0.014-0.092-0.019l-0.004-0h-12c-0.414 0-0.75 0.336-0.75 0.75v0 28c0 0.414 0.336 0.75 0.75 0.75h20c0.414-0 0.75-0.336 0.75-0.75v0-20c-0.005-0.038-0.012-0.071-0.020-0.103l0.001 0.005zM24.189 9.25h-5.439v-5.439zM6.75 29.25v-26.5h10.5v7.25c0 0.414 0.336 0.75 0.75 0.75h7.25v18.5zM20.469 20.91l-3.719 3.721v-10.676c0-0.414-0.336-0.75-0.75-0.75s-0.75 0.336-0.75 0.75v0 10.675l-3.72-3.72c-0.136-0.134-0.322-0.218-0.528-0.218-0.415 0-0.751 0.336-0.751 0.751 0 0.207 0.083 0.394 0.219 0.529l5 5c0.026 0.026 0.065 0.017 0.093 0.038 0.052 0.040 0.088 0.098 0.15 0.124 0.085 0.035 0.184 0.056 0.287 0.057h0c0 0 0 0 0 0 0.207 0 0.394-0.084 0.53-0.219l5.001-5c0.136-0.136 0.22-0.324 0.22-0.531 0-0.415-0.336-0.751-0.751-0.751-0.207 0-0.395 0.084-0.531 0.22v0z"></path>
|
|
6
6
|
</svg>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
3
|
-
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
|
4
|
-
<title>question</title>
|
|
5
|
-
<path d="M19.943 5.251c-1.145-0.635-2.511-1.008-3.964-1.008-1.461 0-2.834 0.378-4.026 1.040l0.042-0.022c-1.649 0.916-2.746 2.648-2.746 4.635 0 0.037 0 0.074 0.001 0.111l-0-0.006c0.001 0.413 0.336 0.747 0.75 0.747 0 0 0 0 0 0h-0c0.407-0.021 0.731-0.346 0.75-0.751l0-0.002c-0.001-0.026-0.001-0.058-0.001-0.089 0-1.441 0.8-2.694 1.98-3.341l0.020-0.010c0.934-0.511 2.047-0.812 3.23-0.812 1.178 0 2.287 0.298 3.255 0.824l-0.036-0.018c1.23 0.657 2.053 1.933 2.053 3.401 0 0.017-0 0.033-0 0.050l0-0.003c0.033 0.19 0.051 0.408 0.051 0.631 0 1.699-1.084 3.145-2.598 3.684l-0.027 0.008c-2.303 1.102-3.424 3.285-3.426 6.677 0 0 0 0 0 0.001 0 0.414 0.335 0.749 0.749 0.749h0.001c0.414-0 0.75-0.336 0.75-0.75v0c0.002-2.793 0.819-4.485 2.586-5.329 2.037-0.783 3.457-2.725 3.457-4.997 0-0.238-0.016-0.473-0.046-0.703l0.003 0.027c0-0.017 0-0.037 0-0.057 0-2.018-1.123-3.774-2.779-4.676l-0.028-0.014zM15.46 25.459c-0.123 0.145-0.198 0.334-0.2 0.541v0c-0.001 0.016-0.002 0.034-0.002 0.052 0 0.082 0.015 0.16 0.044 0.231l-0.002-0.004c0.039 0.094 0.093 0.173 0.16 0.24l0 0c0.071 0.076 0.158 0.137 0.255 0.178l0.005 0.002c0.084 0.026 0.18 0.041 0.28 0.041s0.196-0.015 0.287-0.043l-0.007 0.002c0.102-0.043 0.189-0.104 0.26-0.179l0-0c0.067-0.067 0.12-0.147 0.157-0.235l0.002-0.005c0.038-0.079 0.061-0.173 0.061-0.271 0-0.003-0-0.006-0-0.009v0c-0.010-0.209-0.092-0.397-0.221-0.542l0.001 0.001c-0.145-0.121-0.334-0.195-0.54-0.195s-0.395 0.074-0.541 0.196l0.001-0.001z"></path>
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
3
|
+
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
|
4
|
+
<title>question</title>
|
|
5
|
+
<path d="M19.943 5.251c-1.145-0.635-2.511-1.008-3.964-1.008-1.461 0-2.834 0.378-4.026 1.040l0.042-0.022c-1.649 0.916-2.746 2.648-2.746 4.635 0 0.037 0 0.074 0.001 0.111l-0-0.006c0.001 0.413 0.336 0.747 0.75 0.747 0 0 0 0 0 0h-0c0.407-0.021 0.731-0.346 0.75-0.751l0-0.002c-0.001-0.026-0.001-0.058-0.001-0.089 0-1.441 0.8-2.694 1.98-3.341l0.020-0.010c0.934-0.511 2.047-0.812 3.23-0.812 1.178 0 2.287 0.298 3.255 0.824l-0.036-0.018c1.23 0.657 2.053 1.933 2.053 3.401 0 0.017-0 0.033-0 0.050l0-0.003c0.033 0.19 0.051 0.408 0.051 0.631 0 1.699-1.084 3.145-2.598 3.684l-0.027 0.008c-2.303 1.102-3.424 3.285-3.426 6.677 0 0 0 0 0 0.001 0 0.414 0.335 0.749 0.749 0.749h0.001c0.414-0 0.75-0.336 0.75-0.75v0c0.002-2.793 0.819-4.485 2.586-5.329 2.037-0.783 3.457-2.725 3.457-4.997 0-0.238-0.016-0.473-0.046-0.703l0.003 0.027c0-0.017 0-0.037 0-0.057 0-2.018-1.123-3.774-2.779-4.676l-0.028-0.014zM15.46 25.459c-0.123 0.145-0.198 0.334-0.2 0.541v0c-0.001 0.016-0.002 0.034-0.002 0.052 0 0.082 0.015 0.16 0.044 0.231l-0.002-0.004c0.039 0.094 0.093 0.173 0.16 0.24l0 0c0.071 0.076 0.158 0.137 0.255 0.178l0.005 0.002c0.084 0.026 0.18 0.041 0.28 0.041s0.196-0.015 0.287-0.043l-0.007 0.002c0.102-0.043 0.189-0.104 0.26-0.179l0-0c0.067-0.067 0.12-0.147 0.157-0.235l0.002-0.005c0.038-0.079 0.061-0.173 0.061-0.271 0-0.003-0-0.006-0-0.009v0c-0.010-0.209-0.092-0.397-0.221-0.542l0.001 0.001c-0.145-0.121-0.334-0.195-0.54-0.195s-0.395 0.074-0.541 0.196l0.001-0.001z"></path>
|
|
6
6
|
</svg>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from logging import
|
|
2
|
+
from logging import INFO, WARNING
|
|
3
3
|
|
|
4
4
|
import qcanvas.app_start
|
|
5
5
|
from qcanvas.util import logs, paths
|
|
@@ -17,7 +17,7 @@ logs.set_levels(
|
|
|
17
17
|
"qcanvas": INFO,
|
|
18
18
|
"qcanvas.ui": WARNING,
|
|
19
19
|
"qcanvas_backend": INFO,
|
|
20
|
-
"qcanvas.ui.main_ui.status_bar_progress_display":
|
|
20
|
+
"qcanvas.ui.main_ui.status_bar_progress_display": INFO,
|
|
21
21
|
}
|
|
22
22
|
)
|
|
23
23
|
|
|
@@ -2,6 +2,7 @@ import logging
|
|
|
2
2
|
from abc import abstractmethod
|
|
3
3
|
from typing import *
|
|
4
4
|
|
|
5
|
+
import qcanvas_backend.database.types as db
|
|
5
6
|
from qcanvas_backend.net.sync.sync_receipt import SyncReceipt
|
|
6
7
|
from qtpy.QtCore import QItemSelection, Signal, Slot
|
|
7
8
|
from qtpy.QtWidgets import *
|
|
@@ -12,11 +13,20 @@ from qcanvas.util.basic_fonts import bold_font, normal_font
|
|
|
12
13
|
_logger = logging.getLogger(__name__)
|
|
13
14
|
|
|
14
15
|
T = TypeVar("T")
|
|
16
|
+
U = TypeVar("U", bound=Type["ContentTree"])
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
class ContentTree(MemoryTreeWidget, Generic[T]):
|
|
18
20
|
item_selected = Signal(object)
|
|
19
21
|
|
|
22
|
+
@classmethod
|
|
23
|
+
def create_from_receipt(
|
|
24
|
+
cls: U, course: db.Course, *, sync_receipt: Optional[SyncReceipt]
|
|
25
|
+
) -> Type[U]:
|
|
26
|
+
tree = cls(course.id)
|
|
27
|
+
tree.reload(course, sync_receipt=sync_receipt)
|
|
28
|
+
return tree
|
|
29
|
+
|
|
20
30
|
def __init__(
|
|
21
31
|
self,
|
|
22
32
|
tree_name: str,
|
|
@@ -85,7 +85,3 @@ class CourseTree(ContentTree[Sequence[db.Term]]):
|
|
|
85
85
|
term_widget.setFlags(Qt.ItemFlag.ItemIsEnabled)
|
|
86
86
|
|
|
87
87
|
return term_widget
|
|
88
|
-
|
|
89
|
-
# @Slot(db.Course, str)
|
|
90
|
-
# def _on_course_renamed(self, course: db.Course, new_name: str) -> None:
|
|
91
|
-
# self.course_renamed.emit(course, new_name)
|
{qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/tabs/assignment_tab/assignment_tab.py
RENAMED
|
@@ -16,16 +16,6 @@ _logger = logging.getLogger(__name__)
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class AssignmentTab(ContentTab):
|
|
19
|
-
@staticmethod
|
|
20
|
-
def create_from_receipt(
|
|
21
|
-
*,
|
|
22
|
-
course: db.Course,
|
|
23
|
-
sync_receipt: Optional[SyncReceipt],
|
|
24
|
-
downloader: ResourceManager,
|
|
25
|
-
) -> "AssignmentTab":
|
|
26
|
-
return AssignmentTab(
|
|
27
|
-
course=course, sync_receipt=sync_receipt, downloader=downloader
|
|
28
|
-
)
|
|
29
19
|
|
|
30
20
|
def __init__(
|
|
31
21
|
self,
|
{qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/tabs/assignment_tab/assignment_tree.py
RENAMED
|
@@ -13,14 +13,6 @@ _logger = logging.getLogger(__name__)
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class AssignmentTree(ContentTree[db.Course]):
|
|
16
|
-
@staticmethod
|
|
17
|
-
def create_from_receipt(
|
|
18
|
-
course: db.Course, *, sync_receipt: Optional[SyncReceipt]
|
|
19
|
-
) -> "AssignmentTree":
|
|
20
|
-
tree = AssignmentTree(course.id)
|
|
21
|
-
tree.reload(course, sync_receipt=sync_receipt)
|
|
22
|
-
return tree
|
|
23
|
-
|
|
24
16
|
def __init__(self, course_id: str):
|
|
25
17
|
super().__init__(
|
|
26
18
|
tree_name=f"course.{course_id}.assignment_groups",
|
|
@@ -14,8 +14,20 @@ from qcanvas.util.ui_tools import make_truncatable
|
|
|
14
14
|
|
|
15
15
|
_logger = logging.getLogger(__name__)
|
|
16
16
|
|
|
17
|
+
T = TypeVar("T", bound=Type["ContentTab"])
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
class ContentTab(QWidget):
|
|
21
|
+
@classmethod
|
|
22
|
+
def create_from_receipt(
|
|
23
|
+
cls: T,
|
|
24
|
+
*,
|
|
25
|
+
course: db.Course,
|
|
26
|
+
sync_receipt: Optional[SyncReceipt],
|
|
27
|
+
downloader: ResourceManager,
|
|
28
|
+
) -> Type[T]:
|
|
29
|
+
return cls(course=course, sync_receipt=sync_receipt, downloader=downloader)
|
|
30
|
+
|
|
19
31
|
def __init__(
|
|
20
32
|
self,
|
|
21
33
|
*,
|
|
@@ -17,15 +17,6 @@ _logger = logging.getLogger(__name__)
|
|
|
17
17
|
|
|
18
18
|
# todo maybe update has_been_read? probably not the responsibility of this class though
|
|
19
19
|
class MailTab(ContentTab):
|
|
20
|
-
@staticmethod
|
|
21
|
-
def create_from_receipt(
|
|
22
|
-
*,
|
|
23
|
-
course: db.Course,
|
|
24
|
-
sync_receipt: Optional[SyncReceipt],
|
|
25
|
-
downloader: ResourceManager,
|
|
26
|
-
) -> "MailTab":
|
|
27
|
-
return MailTab(course=course, sync_receipt=sync_receipt, downloader=downloader)
|
|
28
|
-
|
|
29
20
|
def __init__(
|
|
30
21
|
self,
|
|
31
22
|
*,
|
|
@@ -12,13 +12,6 @@ _logger = logging.getLogger(__name__)
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class MailTree(ContentTree[db.Course]):
|
|
15
|
-
@staticmethod
|
|
16
|
-
def create_from_receipt(
|
|
17
|
-
course: db.Course, *, sync_receipt: Optional[SyncReceipt]
|
|
18
|
-
) -> "MailTree":
|
|
19
|
-
tree = MailTree(course.id)
|
|
20
|
-
tree.reload(course, sync_receipt=sync_receipt)
|
|
21
|
-
return tree
|
|
22
15
|
|
|
23
16
|
def __init__(self, course_id: str):
|
|
24
17
|
super().__init__(
|
|
@@ -12,16 +12,6 @@ _logger = logging.getLogger(__name__)
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class PageTab(ContentTab):
|
|
15
|
-
|
|
16
|
-
@staticmethod
|
|
17
|
-
def create_from_receipt(
|
|
18
|
-
*,
|
|
19
|
-
course: db.Course,
|
|
20
|
-
sync_receipt: Optional[SyncReceipt],
|
|
21
|
-
downloader: ResourceManager,
|
|
22
|
-
) -> "PageTab":
|
|
23
|
-
return PageTab(course=course, sync_receipt=sync_receipt, downloader=downloader)
|
|
24
|
-
|
|
25
15
|
def __init__(
|
|
26
16
|
self,
|
|
27
17
|
*,
|
|
@@ -12,14 +12,6 @@ _logger = logging.getLogger(__name__)
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class PageTree(ContentTree[db.Course]):
|
|
15
|
-
@staticmethod
|
|
16
|
-
def create_from_receipt(
|
|
17
|
-
course: db.Course, *, sync_receipt: Optional[SyncReceipt]
|
|
18
|
-
) -> "PageTree":
|
|
19
|
-
tree = PageTree(course.id)
|
|
20
|
-
tree.reload(course, sync_receipt=sync_receipt)
|
|
21
|
-
return tree
|
|
22
|
-
|
|
23
15
|
def __init__(self, course_id: str):
|
|
24
16
|
super().__init__(
|
|
25
17
|
tree_name=f"course.{course_id}.modules",
|
|
@@ -62,7 +62,7 @@ class StatusBarProgressDisplay(QStatusBar):
|
|
|
62
62
|
|
|
63
63
|
@asyncSlot(TaskID, object)
|
|
64
64
|
async def _on_task_failed(self, task_id: TaskID, context: object) -> None:
|
|
65
|
-
_logger.
|
|
65
|
+
_logger.info("%s failed", task_id)
|
|
66
66
|
|
|
67
67
|
async with self._lock:
|
|
68
68
|
self._remove_task(task_id)
|
|
@@ -83,8 +83,8 @@ class StatusBarProgressDisplay(QStatusBar):
|
|
|
83
83
|
self._show_multiple_tasks_progress(list(self._tasks.values()))
|
|
84
84
|
|
|
85
85
|
def _show_done(self) -> None:
|
|
86
|
-
_logger.
|
|
87
|
-
self.showMessage("
|
|
86
|
+
_logger.info("Finished tasks. Tasks: %s", self._tasks)
|
|
87
|
+
self.showMessage("Done", 5000)
|
|
88
88
|
self._progress_bar.hide()
|
|
89
89
|
|
|
90
90
|
def _show_single_task_progress(self, task: Tuple[TaskID, _TaskProgress]) -> None:
|
|
@@ -132,12 +132,12 @@ class StatusBarProgressDisplay(QStatusBar):
|
|
|
132
132
|
|
|
133
133
|
def _add_task(self, task: TaskID, current: int, total: int) -> None:
|
|
134
134
|
self._tasks[task] = _TaskProgress(current, total)
|
|
135
|
-
_logger.
|
|
135
|
+
_logger.info("Added task %s", task)
|
|
136
136
|
_logger.debug("Tasks: %s", self._tasks)
|
|
137
137
|
|
|
138
138
|
def _remove_task(self, task: TaskID) -> None:
|
|
139
139
|
self._tasks.pop(task, None)
|
|
140
|
-
_logger.
|
|
140
|
+
_logger.info("Removed task %s", task)
|
|
141
141
|
_logger.debug("Tasks: %s", self._tasks)
|
|
142
142
|
|
|
143
143
|
@property
|
|
@@ -34,13 +34,16 @@ class SetupDialog(QDialog):
|
|
|
34
34
|
|
|
35
35
|
self._semaphore = Semaphore()
|
|
36
36
|
self._canvas_url_box = QLineEdit(settings.client.canvas_url)
|
|
37
|
+
self._canvas_url_box.setPlaceholderText("https://instance.canvas.com")
|
|
37
38
|
self._canvas_api_key_box = QLineEdit(settings.client.canvas_api_key)
|
|
38
39
|
self._canvas_api_key_box.setEchoMode(QLineEdit.EchoMode.Password)
|
|
39
40
|
self._panopto_url_box = QLineEdit(settings.client.panopto_url)
|
|
41
|
+
self._panopto_url_box.setPlaceholderText("https://instance.panopto.com")
|
|
40
42
|
self._button_box = self._setup_button_box()
|
|
41
43
|
self._button_box.accepted.connect(self._accepted)
|
|
42
44
|
self._button_box.helpRequested.connect(self._help_requested)
|
|
43
45
|
self._waiting_indicator = self._setup_progress_bar()
|
|
46
|
+
self._status_bar = QStatusBar()
|
|
44
47
|
|
|
45
48
|
self.setLayout(
|
|
46
49
|
layout(
|
|
@@ -54,13 +57,14 @@ class SetupDialog(QDialog):
|
|
|
54
57
|
),
|
|
55
58
|
self._waiting_indicator,
|
|
56
59
|
self._button_box,
|
|
60
|
+
self._status_bar,
|
|
57
61
|
)
|
|
58
62
|
)
|
|
59
63
|
|
|
60
64
|
def _setup_button_box(self) -> QDialogButtonBox:
|
|
61
65
|
box = QDialogButtonBox()
|
|
62
66
|
box.addButton(QDialogButtonBox.StandardButton.Ok)
|
|
63
|
-
box.addButton("Get a
|
|
67
|
+
box.addButton("Get a Canvas API key", QDialogButtonBox.ButtonRole.HelpRole)
|
|
64
68
|
return box
|
|
65
69
|
|
|
66
70
|
def _setup_progress_bar(self) -> QProgressBar:
|
|
@@ -81,10 +85,13 @@ class SetupDialog(QDialog):
|
|
|
81
85
|
if self._semaphore.acquire(False):
|
|
82
86
|
try:
|
|
83
87
|
self._clear_errors()
|
|
84
|
-
|
|
88
|
+
|
|
89
|
+
if not self._all_inputs_valid():
|
|
90
|
+
self._status_bar.showMessage("Invalid input!", 5000)
|
|
85
91
|
return
|
|
86
92
|
|
|
87
93
|
self._waiting_indicator.setVisible(True)
|
|
94
|
+
self._status_bar.showMessage("Checking configuration...")
|
|
88
95
|
|
|
89
96
|
canvas_config = CanvasClientConfig(
|
|
90
97
|
api_token=self._canvas_api_key_box.text().strip(),
|
|
@@ -97,7 +104,9 @@ class SetupDialog(QDialog):
|
|
|
97
104
|
if not await self._check_panopto_config(canvas_config):
|
|
98
105
|
self._show_panopto_help()
|
|
99
106
|
return
|
|
100
|
-
|
|
107
|
+
except Exception as e:
|
|
108
|
+
self._status_bar.showMessage(f"An error occurred: {e}", 5000)
|
|
109
|
+
_logger.warning("Checking config failed", exc_info=e)
|
|
101
110
|
finally:
|
|
102
111
|
self._waiting_indicator.setVisible(False)
|
|
103
112
|
self._semaphore.release()
|
|
@@ -113,23 +122,24 @@ class SetupDialog(QDialog):
|
|
|
113
122
|
self._panopto_url_box,
|
|
114
123
|
self._canvas_api_key_box,
|
|
115
124
|
]:
|
|
125
|
+
self._status_bar.clearMessage()
|
|
116
126
|
line_edit.setStyleSheet(None)
|
|
117
127
|
line_edit.setToolTip(None)
|
|
118
128
|
|
|
119
|
-
def
|
|
120
|
-
|
|
129
|
+
def _all_inputs_valid(self) -> bool:
|
|
130
|
+
all_valid = True
|
|
121
131
|
|
|
122
132
|
if not is_url(self._get_url(self._canvas_url_box)):
|
|
123
|
-
|
|
133
|
+
all_valid = False
|
|
124
134
|
self._show_error(self._canvas_url_box, "Canvas URL is invalid")
|
|
125
135
|
if len(self._canvas_api_key_box.text().strip()) == 0:
|
|
126
|
-
|
|
136
|
+
all_valid = False
|
|
127
137
|
self._show_error(self._canvas_api_key_box, "Canvas API key is empty")
|
|
128
138
|
if not is_url(self._get_url(self._panopto_url_box)):
|
|
129
|
-
|
|
139
|
+
all_valid = False
|
|
130
140
|
self._show_error(self._panopto_url_box, "Panopto URL is invalid")
|
|
131
141
|
|
|
132
|
-
return
|
|
142
|
+
return all_valid
|
|
133
143
|
|
|
134
144
|
def _get_url(self, line_edit: QLineEdit) -> str:
|
|
135
145
|
url = line_edit.text().strip()
|
|
@@ -172,8 +182,8 @@ class SetupDialog(QDialog):
|
|
|
172
182
|
msg = QMessageBox(
|
|
173
183
|
QMessageBox.Icon.Information,
|
|
174
184
|
"Panopto Authentication",
|
|
175
|
-
"In order for QCanvas to use
|
|
176
|
-
"A page will open in your web browser to do this when you click OK. It may ask you to sign into
|
|
185
|
+
"In order for QCanvas to use Panopto, you need to link your Panopto account to your Canvas account. "
|
|
186
|
+
"A page will open in your web browser to do this when you click OK. It may ask you to sign into Canvas.\n\n"
|
|
177
187
|
'Please tick "Remember my authorisation for this service" or QCanvas may not function correctly.\n\n'
|
|
178
188
|
"QCanvas can't access anything entered in your browser.",
|
|
179
189
|
QMessageBox.StandardButton.Ok,
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
from urllib.parse import urlparse
|
|
3
|
-
|
|
4
|
-
_logger = logging.getLogger(__name__)
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def is_url(url: str) -> bool:
|
|
8
|
-
# https://overflow.perennialte.ch/questions/7160737/how-to-validate-a-url-in-python-malformed-or-not#
|
|
9
|
-
try:
|
|
10
|
-
result = urlparse(url)
|
|
11
|
-
return all([result.scheme, result.netloc])
|
|
12
|
-
except ValueError:
|
|
13
|
-
return False
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/backend_connectors/frontend_resource_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{qcanvas-1.0.7 → qcanvas-1.0.9.dev0}/qcanvas/ui/course_viewer/tabs/assignment_tab/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|