The EduResourcesView class is a PySide6 widget designed for managing, filtering, and distributing educational resources to students. It serves as the central hub for educators to browse educational content, assign activities to individual students or groups, and generate printable/exportable materials using customizable templates. The class implements a card-based grid interface with advanced filtering, template-based content generation, and student distribution capabilities.
This resource management system supports multiple template types (quiz, formal exam) with configurable layouts, internationalization support, and PDF generation capabilities. It integrates with the application's database to track resource assignments and student progress, creating a seamless workflow from resource selection to student distribution.
The EduResourcesView class provides a comprehensive interface for managing educational resources within a teacher assistant application. It enables educators to:
Browse, filter, and organize educational resources stored in the database with real-time search capabilities.
Assign selected educational items to individual students or groups with customizable deadlines and distribution times.
Generate printable educational materials using configurable templates for different assessment types (quizzes, exams).
/resources/templates/ directory.
The central component is a CardGridView that displays educational resources as interactive cards:
| Pattern | Implementation | Purpose |
|---|---|---|
| Observer Pattern | Signal/Slot connections | Handle user interactions and data updates |
| Worker Pattern | DataLoaderWorker + QThreadPool | Background data loading without UI freeze |
| Template Method | Configurable template system | Generate different output formats |
| Composite Pattern | CardGridView with EduItemWidget children | Manage complex UI hierarchies |
The CardGridView provides a responsive grid layout for educational resource cards:
| Property | Value | Description |
|---|---|---|
| Default Columns | 2 | Number of cards per row |
| Page Size | 50 | Items loaded per batch |
| Card Width | app_context.EDU_ITEM_PIXELS + 20 |
Card width based on A4 paper dimensions |
| Selection Mode | Single/Multiple | Supports selecting multiple resources |
Each card in the grid is an EduItemWidget containing:
The distribution system uses a custom QMenu with embedded widgets:
The class accepts target students as a list of dictionaries:
distribute() - Core Distribution LogicThis method handles the complete distribution process:
quests records for each student-item pairquests table, which links educational resources (qb_id) to students (student_id) with assignment dates, deadlines, and scoring information.
The system provides sensible defaults for distribution timing:
Two primary template types are supported:
| Configuration Key | Purpose | Example Values |
|---|---|---|
Student name |
Placeholder for student name field | "Student name", "نام دانشآموز" |
Book |
Textbook and grade information | "Mathematics Grade 10" |
Date |
Exam/quiz date field | "Date", "تاریخ" |
Font family |
Typography for generated content | "'B Nazanin', Tahoma" |
Direction |
Text direction (RTL/LTR) | "rtl", "ltr" |
Text align |
Content alignment | "right", "left", "center" |
The show_template_selector_dlg() method creates a dynamic dialog based on selected template:
app_context.Language setting. Each configuration key has language-specific values for consistent localization.
Each template type has a specific HTML structure for content rows:
generate_edu_contents() - Main Generation MethodThis method orchestrates the complete content generation process:
The system replaces placeholders in template files with actual content:
The class integrates with PdfGeneratorApp for PDF preview and generation:
get_selected_contents() - Content AggregationThis method collects and processes selected educational resources:
The class uses DataLoaderWorker with QThreadPool for responsive data loading:
| Filter Field | Search Logic | Database Column |
|---|---|---|
| Source | ILIKE (case-insensitive) | source_ |
| Content Description | ILIKE (case-insensitive) | content_description_ |
| Additional Details | ILIKE (case-insensitive) | additional_details_ |
| Resource ID | TEXT conversion + ILIKE | Id |
load_next_page() method constructs SQL queries with string concatenation for the WHERE clause (f"(source_ ILIKE '%{search}' OR ...)"), creating potential SQL injection vulnerabilities. This should be updated to use proper parameterized queries.
The system implements server-side pagination with configurable page size:
| Signal | Slot Method | Purpose |
|---|---|---|
batch_ready |
on_batch_received() |
Process received data batch |
finished |
on_load_finished() |
Handle loading completion |
error |
on_load_error() |
Handle loading errors |
| Method | Purpose | Complexity | Key Operations |
|---|---|---|---|
__init__(parent, target_students) |
Constructor with target students | O(1) | Store target students, initialize defaults |
initUI() |
Main UI construction | O(1) | Create layout, header, card grid, signals |
create_distribution_options() |
Build distribution menu | O(n) for n students | Create QMenu with embedded widgets |
| Method | Primary Function | Performance | Dependencies |
|---|---|---|---|
distribute() |
Distribute resources to students | O(n×m) for n items × m students | Database, target_students, selected items |
get_selected_contents() |
Collect selected resource data | O(n) for n cards | CardGridView, EduItemWidget |
___generate_html_content__() |
Generate HTML from template | O(n) for n placeholders | Template files, app_context |
load_data() |
Initialize data loading | O(1) | DataLoaderWorker, QThreadPool |
template_changed() - Dynamic UI UpdatesThis method dynamically updates the template dialog based on selected template type:
___validate_template__() - Template ValidationValidates template selection and file existence before content generation:
| Method | Trigger | Action |
|---|---|---|
on_card_selected() |
Card selection in grid | Update selected card, show/hide titlebars |
on_card_removed() |
Card removal from grid | Handle card removal (currently placeholder) |
on_batch_received() |
DataLoaderWorker batch | Add cards to grid for received data |
on_load_finished() |
Data loading complete | Update pagination state, show/hide indicators |
on_load_error() |
Data loading error | Display error message in grid |
Issue: Each EduItemWidget contains HTML content
Impact: Linear memory growth with resource count
Solution: Pagination (50 items per page) reduces memory load
Benefit: DataLoaderWorker prevents UI freeze
Impact: Minimal main thread blocking
Optimization: Configurable page size (default: 50)
Issue: HTML template loading and processing
Impact: File I/O and string manipulation overhead
Solution: Template caching could be implemented
| Operation | Method | Complexity | Bottleneck | Optimization Potential |
|---|---|---|---|---|
| Initial data load | load_data() |
O(n) + background loading | Database query, widget creation | Medium - Virtual scrolling |
| Distribution to students | distribute() |
O(n×m) | Database inserts for each student-item pair | High - Batch database operations |
| HTML generation | ___generate_html_content__() |
O(p) for p placeholders | String replacement operations | Low - Already efficient |
| Template switching | template_changed() |
O(1) + file I/O | JSON config loading | Medium - Config caching |
load_next_page()distribute() for better performanceload_next_page() method uses string concatenation for SQL queries with user-provided filter text, creating a severe SQL injection vulnerability. This must be fixed immediately using parameterized queries.
| Method | Parameters | Return | Description | Thread Safety |
|---|---|---|---|---|
__init__(parent, target_students) |
parent: QWidget target_students: list[dict] |
None | Constructor with optional target students | UI thread only |
distribute() |
None | None | Distribute selected resources to target students | UI thread only |
show_template_selector_dlg() |
None | None | Display template selection dialog | UI thread only |
generate_edu_contents() |
None | None | Generate educational content using selected template | UI thread only |
load_data(filter) |
filter: str (optional) | None | Load educational resources with optional filter | UI thread (spawns worker) |
get_selected_contents() |
None | list[dict] | Get data for selected educational resources | UI thread only |
remove_card() |
None | None | Remove selected card from grid | UI thread only |
clear_cards() |
None | None | Clear all cards from grid | UI thread only |
| Signal Source | Signal | Slot/Method | Purpose |
|---|---|---|---|
| Source filter input | textChanged |
load_data(filter=text) |
Real-time filtering of resources |
| CardGridView | card_selected |
on_card_selected |
Handle card selection |
| CardGridView | card_removed |
on_card_removed |
Handle card removal |
| DataLoaderWorker | batch_ready |
on_batch_received |
Process loaded data batches |
| DataLoaderWorker | finished |
on_load_finished |
Handle loading completion |
| DataLoaderWorker | error |
on_load_error |
Handle loading errors |
| Template selector combo | currentIndexChanged |
template_changed |
Update template configuration |
PopupNotifier for user notifications/resources/templates/{name}-Template.html/resources/templates/{name}-config.jsonapp_context.resource_path[DEPENDENCY GRAPH: Visual representation showing:
Core PySide6 → Custom UI Framework (PySideAbdhUI) → Data Loading Layer →
Widget Components → Template Engine → PDF Generation → Database Layer
With bidirectional relationships and data flow directions]