Skip to content

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 a QGraphicsView; theme switches are refreshed automatically via core.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 in i18n/*.ts (see Internationalization).

Common pitfalls

  • core.settings can only resolve the settings path correctly after run.py sets the QCoreApplication organization / application name — otherwise theme / language won't persist across restarts.
  • Do not import PySide6 inside functions/; the computation layer should stay pure and independently testable.