Architecture
CalculusCalculator uses a layered design that separates pure computation from the GUI, so the calculation logic is decoupled from the interface — making it easy to test and extend.
Directory Layout
CalculusCalculator/
├── run.py # Entry point: splash, language/theme init, main window
├── core/ # UI-independent foundation
│ ├── sympify.py # String → SymPy expression (unified input standard)
│ ├── render.py # LaTeX → SVG formula rendering (QGraphicsView)
│ └── settings.py # Persisted settings: language, theme, onboarding flag
├── functions/ # Pure computation modules (no Qt dependency)
│ ├── derivative.py # Differentiation
│ ├── integral.py # Integration
│ ├── functions.py # Expression transformation
│ ├── simplification.py
│ ├── solvers.py # Equations / inequalities / differential equations
│ ├── planes.py # Plane geometry
│ ├── solids.py # Solid geometry
│ ├── paint2D.py / paint3D.py # Plotting
│ └── saves.py # Save / load
├── ui/ # PySide6 tab pages
│ ├── main.py # MainWindow
│ ├── __init__.py # Tab registry (lazy loading)
│ └── <pinyin>.py # Feature pages (e.g. qiudao.py = Derivative)
├── math_input/ # Visual formula input (MathLive editor)
├── blockly/ # Visual block-based computation editor (v2.0.0)
├── i18n/ # Translation sources .ts and compiled .qm
└── docs/ # This help site (mkdocs, zh / en)
Layer Responsibilities
- Entry layer
run.py: configures Qt, pre-initializes WebEngine, loads language and theme, shows the splash screen, builds the main window, and shows the onboarding guide on first launch. - Core layer
core/: provides three UI-independent services — input parsing, formula rendering, and settings persistence. Every feature page relies oncore.sympifyto parse input andcore.renderto render results. - Computation layer
functions/: each module exposes pure functions (SymPy expressions / parameters in, SymPy objects or strings out) with no Qt dependency, enabling standalone unit tests. - UI layer
ui/: each feature is aQWidgetsubclass (page).ui/__init__.pykeeps a "tab registry" and useslazy_loaderso a module is imported only when its tab is first created, speeding up startup. - Visual input
math_input//blockly/: provide structured formula input and block-based flow editing respectively; both ultimately produce a standard SymPy expression that is handed to the computation layer.
Data Flow
User input → core.sympify.sympify() → SymPy expression
→ functions.<module>.<func>() → SymPy result
→ core.render.setGraphicsView() → SVG
→ QGraphicsView (live LaTeX rendering)
Tab Registry
_tab_registry, tabs_dict, and tabs_list in ui/__init__.py are the single source of truth mapping "feature page ↔ tab". A new feature must be registered in all three places (see Adding a Feature Tab).
Tip
For the public functions of each module, see the API Reference.