Skip to content

Architecture Overview

techy4shri edited this page Nov 29, 2025 · 4 revisions

Architecture Overview

This document describes the high-level architecture and design of CppLab IDE. Now, keep in mind that everything shown here is just the gist of what I did. I do plan on putting a proper diagram here once my exams are over but for now, I just wanted a pretty wiki with some basic diagram, and here it is. Now, this is mostly for documenting purposes but if you want to understand what was I thinking, making an IDE for C/C++ in Python, well, this is a good place to start.

System Architecture

CppLab IDE follows a layered architecture with clear separation of concerns:

┌─────────────────────────────────────────────────────────────┐
│                     User Interface Layer                    │
│  (PyQt6 - MainWindow, Dialogs, Widgets)                     │
├─────────────────────────────────────────────────────────────┤
│                    Application Logic Layer                  │
│  (Project Management, File Management, Settings)            │
├─────────────────────────────────────────────────────────────┤
│                   Build & Execution Layer                   │
│  (Async BuildWorker, Toolchain Management, Compiler)        │
├─────────────────────────────────────────────────────────────┤
│                    Data Persistence Layer                   │
│  (JSON Config Files, Settings Storage)                      │
└─────────────────────────────────────────────────────────────┘

Directory Structure

CppLabEngine/
├── src/cpplab/              # Main application package
│   ├── __init__.py          # Package init with version
│   ├── main.py              # Application entry point
│   ├── app.py               # MainWindow class (1000+ lines)
│   ├── dialogs.py           # Project dialogs (NewProject, etc.)
│   ├── settings.py          # Settings data model and persistence
│   ├── settings_dialog.py   # Settings UI dialog
│   │
│   ├── ui/                  # Qt Designer UI files
│   │   ├── MainWindow.ui
│   │   └── NewProjectDialog.ui
│   │
│   ├── widgets/             # Custom Qt widgets
│   │   ├── code_editor.py      # Syntax-highlighted editor
│   │   ├── project_explorer.py # File tree view
│   │   └── output_panel.py     # Build output display
│   │
│   └── core/                # Core business logic
│       ├── project_config.py   # Project data model
│       ├── toolchains.py       # Compiler configuration
│       └── builder.py          # Build system (500+ lines)
│
├── compilers/               # Bundled MinGW toolchains
│   ├── mingw32/             # 32-bit (graphics.h)
│   └── mingw64/             # 64-bit (OpenMP)
│
├── docs/                    # Offline documentation
├── examples/                # Sample projects
├── tests/                   # Unit and integration tests
└── tools/                   # Build and release scripts
    └── build_release.py

Core Components

1. MainWindow (app.py)

Responsibilities:

  • Central application controller
  • UI event handling and routing
  • State management (current project, open files)
  • Async build coordination

Key Attributes:

self.current_project: Optional[ProjectConfig]   # Active project
self.toolchains: dict                           # MinGW toolchains
self.open_editors: dict[str, CodeEditor]        # Open file editors
self.build_in_progress: bool                    # Async build state
self.settings: AppSettings                      # User preferences

Key Methods:

  • start_build_task() - Initiate async builds
  • on_build_finished() - Handle build completion
  • build_current() / run_current() - Build/run workflows
  • apply_settings() - Apply theme and font changes

2. BuildWorker (app.py)

Responsibilities:

  • Execute compilation in background thread
  • Emit progress signals to UI
  • Handle build errors gracefully

Architecture:

class BuildWorker(QObject):
    started = pyqtSignal()
    finished = pyqtSignal(object)  # BuildResult
    error = pyqtSignal(str)
    
    def run(self):
        # Executes in QThread
        # Calls builder.py functions
        # Emits signals to MainWindow

3. Build System (core/builder.py)

Responsibilities:

  • Compile C/C++ source files
  • Manage incremental builds
  • Link with appropriate libraries
  • Auto-detect features (graphics.h, OpenMP)

Key Functions:

build_project(config, toolchains, force_rebuild) -> BuildResult
build_single_file(path, toolchains, ...) -> BuildResult
check_project(config, toolchains) -> BuildResult  # Syntax only
check_single_file(path, toolchains, ...) -> BuildResult

BuildResult Structure:

@dataclass
class BuildResult:
    success: bool
    command: list[str]
    stdout: str
    stderr: str
    exe_path: Optional[Path]
    elapsed_ms: float
    skipped: bool

4. Toolchain Manager (core/toolchains.py)

Responsibilities:

  • Discover MinGW installations
  • Select appropriate toolchain (32/64-bit)
  • Provide compiler paths and flags

Toolchain Selection Logic:

if graphics_required:
    toolchain = mingw32  # 32-bit required for WinBGIm
elif openmp_required:
    toolchain = mingw64  # 64-bit recommended for OpenMP
else:
    toolchain = mingw64  # Default to 64-bit

5. Project Configuration (core/project_config.py)

Responsibilities:

  • Store project metadata
  • Serialize/deserialize to JSON
  • Manage source file lists

Structure:

@dataclass
class ProjectConfig:
    name: str
    root_path: Path
    language: str              # "c" or "cpp"
    standard: str              # "c17", "c++20", etc.
    project_type: str          # "console" or "graphics"
    features: dict             # {"graphics": bool, "openmp": bool}
    files: list[str]
    main_file: str
    toolchain_preference: str  # "auto", "mingw32", "mingw64"

6. Custom Widgets

CodeEditor (widgets/code_editor.py)

  • Syntax highlighting via QSyntaxHighlighter
  • Line numbers in margin
  • Modified state tracking
  • File path association

ProjectExplorer (widgets/project_explorer.py)

  • QTreeView-based file browser
  • File double-click → open in editor
  • Context menu (future: add/remove files)

OutputPanel (widgets/output_panel.py)

  • Build output display
  • Auto-scroll to bottom
  • Monospace font (Consolas)
  • Clear/append operations

Data Flow

Build Flow

User Action (Fn+F5 or F5/F7)
    ↓
MainWindow.build_current()
    ↓
start_build_task()
    ↓
Create BuildWorker + QThread
    ↓
worker.run() [Background Thread]
    ↓
builder.build_project/build_single_file()
    ↓
Execute g++/gcc command
    ↓
BuildResult with elapsed_ms
    ↓
worker.finished signal
    ↓
MainWindow.on_build_finished()
    ↓
Update UI (status bar, output panel)

Project Load Flow

User: File → Open Project
    ↓
MainWindow.on_open_project()
    ↓
Load cpplab_project.json
    ↓
ProjectConfig.load()
    ↓
Update UI (tree, toolchain combo, standard combo)
    ↓
Open main file in editor

Threading Model

Main Thread (Qt Event Loop)

  • All UI operations
  • User input handling
  • Signal/slot connections
  • Widget updates

Background Threads (QThread)

  • Build operations (BuildWorker)
  • File operations (future: large file loading)
  • External process monitoring (future: debugger)

Thread Safety

  • BuildWorker uses QObject + moveToThread() pattern (PyQt6 best practice)
  • No direct UI updates from worker threads
  • All communication via Qt signals (thread-safe)
  • Worker auto-deleted after completion (deleteLater())

State Management

Application State

# Global
current_project: Optional[ProjectConfig]
open_editors: dict[str, CodeEditor]
standalone_files: set[Path]

# Build State
build_in_progress: bool
current_build_thread: Optional[QThread]
_pending_run_after_build: bool

# Settings
settings: AppSettings  # Loaded from ~/.cpplab/settings.json

Project State (Persistent)

  • Stored in <project_root>/cpplab_project.json
  • Version controlled with project
  • Contains all build configuration

User Settings (Persistent)

  • Stored in ~/.cpplab/settings.json
  • User-specific preferences
  • Not version controlled

Design Patterns

1. MVC (Model-View-Controller)

  • Model: ProjectConfig, AppSettings
  • View: Qt Widgets (.ui files)
  • Controller: MainWindow (app.py)

2. Observer Pattern

  • Qt Signals/Slots for event handling
  • BuildWorker emits progress signals
  • Widgets emit interaction signals

3. Factory Pattern

  • create_new_project() creates ProjectConfig
  • Toolchain selection based on features

4. Builder Pattern

  • BuildResult accumulates build information
  • Command construction in builder.py

5. Strategy Pattern

  • Different build strategies (project vs standalone)
  • Toolchain selection strategies

Error Handling

UI Layer

  • QMessageBox for user-facing errors
  • Non-blocking error dialogs
  • Status bar for quick feedback

Build Layer

  • Try/catch in BuildWorker.run()
  • Emit error signal on exception
  • BuildResult captures compiler errors

File Operations

  • Path validation before operations
  • Exception handling with user feedback
  • Auto-create directories as needed

Extension Points

Future enhancements can be added at these points:

  1. [] New Project Types: Add to ProjectConfig.project_type
  2. [] Additional Toolchains: Extend toolchains.py
  3. Language Support: Add syntax highlighters
  4. [] Build Profiles: Add Debug/Release modes
  5. [] Plugin System: Load external Python modules

Performance Considerations

Fast Startup

  • Lazy widget initialization
  • Toolchain discovery cached
  • UI loaded from .ui files (fast)

Responsive Builds

  • Asynchronous compilation (no freezing)
  • Incremental builds (skip unchanged)
  • Syntax-only checks (fast feedback)

Memory Efficiency

  • Single OutputPanel shared
  • Editors created on-demand
  • Build threads auto-deleted

Disk I/O

  • JSON config files (small, fast)
  • Minimal file watching (manual reload)
  • Build artifacts in separate build/ dir

Next: Asynchronous Build System

Clone this wiki locally