Adding a Feature Tab
Every feature in this app is presented as a tab. Adding a new feature takes three steps: create the page class, register it in the tab registry, and wire up the core services.
1. Create the page module
Create a new file under ui/ whose name uses the Chinese pinyin of the feature (consistent with the existing convention, e.g. qiudao.py, jifen.py). Define a page class that subclasses QWidget:
# ui/xin_gongneng.py
from PySide6.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel
from PySide6.QtCore import QCoreApplication
class XinGongneng(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.fs = None # function dict (optional; passed by main window)
layout = QVBoxLayout(self)
self.label = QLabel(QCoreApplication.translate("XinGongneng", "New Feature"))
layout.addWidget(self.label)
btn = QPushButton(QCoreApplication.translate("XinGongneng", "Compute"))
btn.clicked.connect(self.compute)
layout.addWidget(btn)
def compute(self):
# Parse input (unified standard: $ LaTeX prefix, custom funcs, sets/intervals)
from functions.derivative import derivative
res = derivative("x**2", "x") # returns a SymPy expression
# Render the result into a QGraphicsView
from core.render import setGraphicsView
setGraphicsView("", str(res), self.graphics_view)
Tip
By convention the page class's second constructor argument is fs (function dict / cache), passed by the main window when the tab is created; omit it if unused. Prefer calling pure functions in functions/ to keep UI and logic decoupled.
2. Register in the tab registry
Edit ui/__init__.py and add entries to _submodules, _tab_registry, and tabs_dict (increment the index, keep it unique):
_submodules = [..., "xin_gongneng"]
_tab_registry = [..., ("xin_gongneng", "XinGongneng")]
tabs_dict = {..., "New Feature": 23}
tabs_list is a lazy-loading proxy and needs no change. run.py will automatically add the new page to the tab bar on startup.
3. Wire up core services
- Input parsing: use
core.sympify.sympify(expr, fs, is_simplify=..., is_rationalize=...)to get the unified input standard ($LaTeX prefix, custom functions, sets / intervals, etc.). - Result rendering: use
core.render.setGraphicsView(name, latex_str, graphics_view)to render the result as SVG in aQGraphicsView; theme switches are refreshed automatically viacore.render.refreshGraphicsView(). - Theme / language: read and switch via
core.settings.current_theme()/apply_language()— no manual management needed. - Internationalization: wrap all user-visible strings with
QCoreApplication.translate("Context", "text")and add translations ini18n/*.ts(see Internationalization).
Common pitfalls
core.settingscan only resolve the settings path correctly afterrun.pysets theQCoreApplicationorganization / application name — otherwise theme / language won't persist across restarts.- Do not
import PySide6insidefunctions/; the computation layer should stay pure and independently testable.