The EducationalResourceEditor class is a sophisticated PySide6-based editor designed for creating and managing educational resources in multiple formats. It serves as a unified editing interface for plain text, rich text (RTF), HTML, LaTeX, images, PDF documents, and more. The editor implements a dual-content architecture with separate areas for educational content and answer sections, each supporting the full range of document formats.
This editor uses HTML as its underlying storage format, with specialized handling for different content types. All content is formatted to A4 paper width (6.19 inches after margins) to ensure consistency in printed output. The system intelligently detects content type and applies appropriate rendering and editing capabilities, making it a versatile tool for educators creating diverse learning materials.
The EducationalResourceEditor implements a comprehensive editing solution for educational materials with the following design principles:
All content formatted to 6.19 inches width (A4 paper minus margins). Content width calculated as 6.19 Γ DPI pixels for consistent printing.
Uses HTML as underlying storage format with meta tags for type identification. Differentiates between raw content and processed HTML rendering.
Separate editing areas for educational content and answers. Each area supports full range of document formats with specialized toolbars.
app_context.EDU_ITEM_PIXELS = 6.19 Γ DPI.
The editor uses a 5-row Γ 6-column grid layout for precise control over widget placement:
| Editor Area | Widget Type | Width | Purpose | Supported Formats |
|---|---|---|---|---|
| Content Editor | RichTextEdit |
EDU_ITEM_PIXELS + 35 |
Primary educational content | All formats (text, HTML, LaTeX, images, PDF) |
| Answer Editor | QTextEdit |
EDU_ITEM_PIXELS + 35 |
Answer/solution content | All formats (text, HTML, LaTeX, images, PDF) |
The right panel (columns 1-5) contains metadata and configuration fields:
| Component | Type | Purpose | Row/Column |
|---|---|---|---|
| Source Input | QLineEdit |
Resource source/book reference | Row 1, Columns 2-3 |
| Additional Details | QTextEdit |
Notes, comments, metadata | Row 2, Columns 1-4 |
| Score Input | QLineEdit |
Point value for assessment | Row 3, Column 2 |
| Delete Button | QPushButton |
Remove current record | Row 3, Column 3 |
| Save Button | QPushButton |
Save to database | Row 3, Column 4 |
Both content and answer sections have dedicated command toolbars with similar functionality:
[UI LAYOUT DIAGRAM: Showing the 5Γ6 grid structure:
β’ Top row: Title and navigation β’ Rows 1-4: Content/Answer with toolbars
β’ Right panel: Metadata fields β’ Bottom: Action buttons
β’ Color-coded sections showing widget relationships]
Storage: Converted to HTML via toHtml()
Restoration: Loaded via setHtml()
Limitations: No formatting, math, or images
Storage: Saved as HTML via toHtml()
Restoration: Loaded via setHtml()
Features: Formatting, images, tables
Storage: Saved raw via toPlainText()
Restoration: Loaded via setPlainText()
Processing: Requires LaTeX engine
Storage: Saved raw via toPlainText()
Restoration: Loaded via setPlainText()
Processing: Interpreted via setHtml()
Storage: Base64 encoded in HTML <img> tag
Restoration: Loaded via setHtml()
Width: Fixed to EDU_ITEM_PIXELS
Options: Editable (text) or Readonly (image)
Processing: PyMuPDF for extraction
Limitation: First page only for multi-page PDFs
helpers.is_rtf() - Format DetectionThe system uses helpers.is_rtf() to distinguish between raw text (HTML/LaTeX) and processed text (Plain Text/RTF):
The editor uses HTML meta tags to identify content types in the database:
upload_file() - Unified File ProcessingThis method handles all file uploads with type-specific processing:
| Source | Processing | Output | Insertion Method |
|---|---|---|---|
| File Upload | pixmap_to_base64() |
Base64 string | setHtml() or insertHtml() |
| Screen Capture | SnippingWindow β pixmap_to_base64() |
Base64 string | insertHtml() |
| PDF Conversion | pdf_to_base64() |
Base64 string array | setHtml() (first page only) |
| LaTeX Rendering | helpers.run_latex() |
HTML with embedded image | insertHtml() |
The editor provides comprehensive LaTeX support through multiple methods:
run_latex() method requires a working LaTeX installation with xepersian package. This is an external dependency that must be installed separately on the user's system.
The editor integrates a snipping tool for capturing screen content:
| Field Name | Type | Purpose | Editor Widget |
|---|---|---|---|
Id |
Primary Key | Unique resource identifier | Id_label (display only) |
source_ |
Text | Resource source/book reference | source_input (QLineEdit) |
score_ |
Numeric | Point value for assessment | score_input (QLineEdit) |
content_description_ |
Text | Primary educational content | content_description_input (RichTextEdit) |
answer_ |
Text | Answer/solution content | answer_input (QTextEdit) |
additional_details_ |
Text | Notes, comments, metadata | additional_details_input (QTextEdit) |
save_to_database() - Intelligent Save LogicThis method handles both insert (new) and update (existing) operations:
load_record() - Navigation and LoadingSupports multiple navigation modes with intelligent content type detection:
| Direction | Query Logic | Purpose |
|---|---|---|
'<' (Back) |
Id < current_id ORDER BY Id DESC |
Previous record (lower ID) |
'>' (Next) |
Id > current_id ORDER BY Id ASC |
Next record (higher ID) |
'=' (Specific) |
Id = specific_id |
Load specific record by ID |
'' (Empty) |
Id > 0 ORDER BY Id DESC |
Most recent record |
remove_record() method uses string concatenation for the DELETE query (f"DELETE FROM educational_resources WHERE id={self.id};"). While the ID comes from internal state, this pattern should be replaced with parameterized queries for consistency and security best practices.
| Method | Purpose | Complexity | Key Operations |
|---|---|---|---|
__init__(cursor) |
Constructor with database cursor | O(1) | Grid layout creation, widget initialization |
create_right_panel() |
Build right-side metadata panel | O(1) | Add source, details, score, navigation widgets |
create_content_commands() |
Build content command toolbar | O(1) | Create LaTeX, HTML, image, upload, search buttons |
create_answer_commands() |
Build answer command toolbar | O(1) | Mirror of content toolbar for answer editor |
| Method | Primary Function | Performance | Dependencies |
|---|---|---|---|
upload_file() |
Process file uploads of all types | O(n) for file size | File I/O, image conversion, PDF processing |
read_plain_text() |
Load plain text files | O(n) for file size | File I/O, text encoding detection |
upload_PDF_as_html() |
Extract text from PDFs | O(p) for PDF pages | PyMuPDF, HTML generation |
run_latex() |
Compile and render LaTeX | External process | LaTeX engine, helpers.run_latex() |
run_html() |
Interpret HTML source | O(n) for HTML size | HTML parser, Qt rendering |
run_snipping_tool() |
Capture screen content | O(1) + image processing | SnippingWindow, image conversion |
___config_basic_html() - HTML Template CreationCreates a basic HTML template with proper document structure:
___config_latex() - LaTeX Template CreationCreates a Persian-enabled LaTeX template with highlighting:
| Method | Purpose | Implementation |
|---|---|---|
___highlightText() |
Highlight specific text in editor | Uses QTextCursor and QTextCharFormat |
clear_content() |
Reset all editor fields | Calls clear() on all widgets |
load_from_database() |
Load specific record by ID | Wrapper for load_record('=') |
remove_record() |
Delete current record | DELETE query with confirmation dialog |
| File Extension | Detection Method | Processing Function | Storage Format |
|---|---|---|---|
.txt |
Extension check | read_plain_text() β setHtml() |
HTML (via toHtml()) |
.tex |
Extension check | read_plain_text() β setPlainText() |
Raw LaTeX |
.html |
Extension check | read_plain_text() β setPlainText() |
Raw HTML |
.rtf |
Extension check | pypandoc.convert_file() (commented) |
HTML (converted) |
| Image files | MIME type filter | pixmap_to_base64() β HTML <img> |
Base64 in HTML |
.pdf |
Extension check + options | pdf_to_base64() or upload_PDF_as_html() |
Base64 image or HTML text |
.docx |
Extension check | pypandoc.convert_file() (commented) |
HTML (converted) |
All images resized to EDU_ITEM_PIXELS width via HTML width attribute. Maintains aspect ratio. Ensures print compatibility.
Images converted to base64 strings for direct embedding. No external file dependencies. Increases database size but improves portability.
Replace: Clear editor, insert as new content.
Append: Insert at cursor position.
Controlled by options parameter.
The editor provides two PDF processing modes:
The editor uses multiple strategies to determine content type:
Issue: Base64 encoding increases size by ~33%
Impact: Large images/PDFs consume significant memory
Solution: Fixed width limits, single-page PDF processing
Issue: Large documents in text editors
Impact: Linear memory growth with document size
Solution: Qt's efficient text document management
Issue: LaTeX compilation is external process
Impact: High CPU/memory during compilation
Solution: Async processing, progress indicators
| Operation | Method | Complexity | Bottleneck | Optimization Potential |
|---|---|---|---|---|
| File upload (image) | upload_file() |
O(n) for image size | Base64 encoding, pixmap loading | Medium - Thumbnail generation |
| PDF processing | upload_PDF_as_html() |
O(p) for PDF pages | PyMuPDF text extraction | Low - Already limited to first page |
| LaTeX compilation | run_latex() |
External process | LaTeX engine startup and compilation | Low - External dependency |
| Database save/load | save_to_database() |
O(1) + network | Database connection, text size | Medium - Connection pooling |
| Screen capture | run_snipping_tool() |
O(1) + image processing | Fullscreen capture, base64 encoding | Low - Already efficient |
remove_record()| Dependency | Purpose | Impact | Alternative |
|---|---|---|---|
| PyMuPDF | PDF text extraction | Essential for editable PDFs | PDFMiner, pdfplumber |
| LaTeX Engine | Formula rendering | Critical for math content | MathJax (web), KaTeX |
| pypandoc | Document conversion | Optional (commented out) | python-docx, mammoth |
| Method | Parameters | Return | Description | Thread Safety |
|---|---|---|---|---|
__init__(cursor) |
cursor: database cursor | None | Constructor with database connection | UI thread only |
upload_file(sender, arg, options) |
sender: QTextEdit arg: file type options: str or None |
None | Upload and process file of specified type | UI thread only |
run_latex(sender) |
sender: QTextEdit | None | Compile LaTeX source and insert result | UI thread (spawns external process) |
run_html(sender) |
sender: QTextEdit | None | Interpret HTML source and render | UI thread only |
run_snipping_tool(target) |
target: QTextEdit | None | Capture screen and insert as image | UI thread only |
save_to_database() |
None | None | Save current content to database | UI thread only |
load_record(direction) |
direction: str ('<', '>', '=', '') | None | Load record based on navigation direction | UI thread only |
load_from_database(sender) |
sender: QLineEdit | None | Load specific record by ID from input | UI thread only |
remove_record() |
None | None | Delete current record with confirmation | UI thread only |
clear_content() |
None | None | Reset all editor fields to empty | UI thread only |
| Method | Access | Purpose | Notes |
|---|---|---|---|
___config_basic_html() |
Private | Create HTML template | Called from HTML button menu |
___config_latex() |
Private | Create LaTeX template | Called from LaTeX button menu |
___highlightText() |
Private | Highlight text in editor | Used in template creation |
read_plain_text() |
Private | Load plain text files | Helper for upload_file() |
upload_PDF_as_html() |
Private | Extract PDF text as HTML | PDF editable mode processing |
| Signal Source | Signal | Slot/Method | Purpose |
|---|---|---|---|
| Back navigation button | clicked |
lambda: load_record('<') |
Load previous record |
| Next navigation button | clicked |
lambda: load_record('>') |
Load next record |
| Save button | clicked |
save_to_database |
Save current content |
| Delete button | clicked |
remove_record |
Delete current record |
| SnippingWindow | screen_captured |
Lambda inserting base64 image | Insert captured screen image |
| Database search button | clicked |
load_from_database |
Load record by ID |
pixmap_to_base64()SnippingWindow for screen capturepdf_to_base64()run_latex(), is_rtf()PopupNotifier for user feedback[FLOW DIAGRAM: Showing content processing pipeline:
Input Sources β Format Detection β Type-Specific Processing β
Storage Format Conversion β Database Integration β Output Rendering
With parallel paths for different content types and conversion options]