Skip to content

Settings And Configuration

techy4shri edited this page Nov 25, 2025 · 1 revision

Settings and Configuration

CppLab IDE provides user-configurable settings for customizing appearance, build behavior, and development preferences.

Settings Storage

Location

User Settings File:

Windows: C:\Users\<Username>\.cpplab\settings.json
Linux:   ~/.cpplab/settings.json
macOS:   ~/.cpplab/settings.json

Format: JSON

Example:

{
  "theme": "classic",
  "font_size": 10,
  "bold_font": false,
  "auto_save": true,
  "show_line_numbers": true,
  "tab_width": 4,
  "default_standard_c": "c17",
  "default_standard_cpp": "c++17",
  "default_toolchain": "mingw64",
  "build_before_run": true,
  "show_build_time": true
}

Persistence

When Settings Are Saved:

  • On settings dialog "OK" button
  • On application exit (window position/size)
  • On theme change
  • On font change

When Settings Are Loaded:

  • On application startup
  • On settings dialog open
  • After settings change

Settings Dialog

Access

Method 1: Menu

Tools → Settings... (Alt+S)

Method 2: Toolbar

Click ⚙ (Settings) icon

Method 3: Keyboard

Ctrl+Comma

Dialog Structure

┌─────────────────────────────────────────┐
│ Settings                          [X]   │
├─────────────────────────────────────────┤
│ ┌─────────────────────────────────────┐ │
│ │ [Appearance] [Build] [Editor] [Advanced] │
│ └─────────────────────────────────────┘ │
│                                         │
│  Theme:          [Classic        ▼]    │
│  Font Size:      [10             ▼]    │
│  ☑ Bold Font                            │
│  ☑ Show Line Numbers                    │
│                                         │
│               [OK]  [Cancel]  [Apply]   │
└─────────────────────────────────────────┘

Settings Categories

Appearance

Theme:

Options: Classic, Sky Blue, Dark (future)
Default: Classic
Description: Overall color scheme

Font Settings:

Font Size: 8, 9, 10, 11, 12, 14, 16, 18, 20
Default: 10
Description: Size of text in editor and output panels

Font Family: Consolas (fixed)
Description: Monospace font for code

Bold Font: Checkbox
Default: Unchecked
Description: Make all text bold

UI Scale (future):

Options: 100%, 125%, 150%, 200%
Default: 100%
Description: Scale entire UI

Build

Default Standards:

C Standard:   C99, C11, C17, C18, C23
Default:      C17
Description:  Default for new C projects

C++ Standard: C++11, C++14, C++17, C++20, C++23
Default:      C++17
Description:  Default for new C++ projects

Default Toolchain:

Options:     mingw32, mingw64
Default:     mingw64
Description: Toolchain for new projects

Build Behavior:

☑ Build Before Run
  Default: Checked
  Description: Automatically build before running

☑ Show Build Time
  Default: Checked
  Description: Display elapsed time in status bar

☑ Save All Before Build
  Default: Checked
  Description: Save all open files before building

☐ Verbose Build Output
  Default: Unchecked
  Description: Show detailed compiler output

Optimization Level:

Options: -O0 (None), -O1 (Basic), -O2 (Moderate), -O3 (Aggressive)
Default: -O0
Description: Compiler optimization level

Editor

Indentation:

Tab Width: 2, 4, 8
Default:   4
Description: Number of spaces per tab

☐ Use Spaces Instead of Tabs
  Default: Unchecked
  Description: Insert spaces when Tab key pressed

Display:

☑ Show Line Numbers
  Default: Checked
  Description: Show line numbers in gutter

☐ Show Whitespace
  Default: Unchecked
  Description: Show spaces and tabs

☑ Highlight Current Line
  Default: Checked
  Description: Highlight line with cursor

Behavior:

☑ Auto-Indent
  Default: Checked
  Description: Auto-indent on newline

☑ Auto-Complete Brackets
  Default: Checked
  Description: Auto-close {}, [], (), ""

☑ Word Wrap
  Default: Unchecked
  Description: Wrap long lines

Advanced

Paths:

Toolchain Directory:   [Browse...]
Default: compilers/ (relative to exe)
Description: Location of MinGW toolchains

Project Templates Dir: [Browse...]
Default: templates/ (relative to exe)
Description: Custom project templates

Performance:

Max Undo History: 100, 500, 1000, Unlimited
Default:          1000
Description:      Number of undo steps

Max File Size:    1 MB, 5 MB, 10 MB, 50 MB
Default:          10 MB
Description:      Max file size to open

Debugging:

☐ Enable Debug Logging
  Default: Unchecked
  Description: Write logs to cpplab.log

☐ Show Internal Errors
  Default: Unchecked
  Description: Show Python tracebacks

Implementation

Data Model

File: src/cpplab/settings.py

from dataclasses import dataclass, asdict
from pathlib import Path
import json

@dataclass
class AppSettings:
    """Application settings."""
    # Appearance
    theme: str = "classic"
    font_size: int = 10
    bold_font: bool = False
    
    # Build
    default_standard_c: str = "c17"
    default_standard_cpp: str = "c++17"
    default_toolchain: str = "mingw64"
    build_before_run: bool = True
    show_build_time: bool = True
    optimization_level: str = "-O0"
    
    # Editor
    tab_width: int = 4
    use_spaces: bool = False
    show_line_numbers: bool = True
    auto_indent: bool = True
    
    # Advanced
    max_undo_history: int = 1000
    max_file_size_mb: int = 10
    debug_logging: bool = False

def get_settings_path() -> Path:
    """Get path to settings file."""
    settings_dir = Path.home() / ".cpplab"
    settings_dir.mkdir(exist_ok=True)
    return settings_dir / "settings.json"

def load_settings() -> AppSettings:
    """Load settings from JSON file."""
    settings_path = get_settings_path()
    
    if not settings_path.exists():
        # Return defaults
        return AppSettings()
    
    try:
        with open(settings_path, 'r', encoding='utf-8') as f:
            data = json.load(f)
            return AppSettings(**data)
    except Exception as e:
        print(f"Error loading settings: {e}")
        return AppSettings()

def save_settings(settings: AppSettings):
    """Save settings to JSON file."""
    settings_path = get_settings_path()
    
    try:
        with open(settings_path, 'w', encoding='utf-8') as f:
            json.dump(asdict(settings), f, indent=2)
    except Exception as e:
        print(f"Error saving settings: {e}")

Settings Dialog

File: src/cpplab/settings_dialog.py

from PyQt6.QtWidgets import (
    QDialog, QTabWidget, QVBoxLayout, QHBoxLayout,
    QLabel, QComboBox, QCheckBox, QPushButton,
    QGroupBox, QSpinBox
)
from PyQt6.QtCore import Qt

class SettingsDialog(QDialog):
    """Settings dialog with tabbed interface."""
    
    def __init__(self, current_settings: AppSettings, parent=None):
        super().__init__(parent)
        self.settings = current_settings
        self.setWindowTitle("Settings")
        self.resize(500, 400)
        
        # Create layout
        layout = QVBoxLayout()
        
        # Create tabs
        tabs = QTabWidget()
        tabs.addTab(self._create_appearance_tab(), "Appearance")
        tabs.addTab(self._create_build_tab(), "Build")
        tabs.addTab(self._create_editor_tab(), "Editor")
        
        layout.addWidget(tabs)
        
        # Buttons
        button_layout = QHBoxLayout()
        button_layout.addStretch()
        
        ok_button = QPushButton("OK")
        ok_button.clicked.connect(self.accept)
        
        cancel_button = QPushButton("Cancel")
        cancel_button.clicked.connect(self.reject)
        
        apply_button = QPushButton("Apply")
        apply_button.clicked.connect(self.apply_settings)
        
        button_layout.addWidget(ok_button)
        button_layout.addWidget(cancel_button)
        button_layout.addWidget(apply_button)
        
        layout.addLayout(button_layout)
        self.setLayout(layout)
    
    def _create_appearance_tab(self):
        """Create appearance settings tab."""
        widget = QWidget()
        layout = QVBoxLayout()
        
        # Theme
        theme_group = QGroupBox("Theme")
        theme_layout = QVBoxLayout()
        
        self.theme_combo = QComboBox()
        self.theme_combo.addItems(["classic", "sky_blue"])
        self.theme_combo.setCurrentText(self.settings.theme)
        
        theme_layout.addWidget(QLabel("Theme:"))
        theme_layout.addWidget(self.theme_combo)
        theme_group.setLayout(theme_layout)
        
        # Font
        font_group = QGroupBox("Font")
        font_layout = QVBoxLayout()
        
        self.font_size_spin = QSpinBox()
        self.font_size_spin.setRange(8, 20)
        self.font_size_spin.setValue(self.settings.font_size)
        
        self.bold_check = QCheckBox("Bold Font")
        self.bold_check.setChecked(self.settings.bold_font)
        
        font_layout.addWidget(QLabel("Font Size:"))
        font_layout.addWidget(self.font_size_spin)
        font_layout.addWidget(self.bold_check)
        font_group.setLayout(font_layout)
        
        layout.addWidget(theme_group)
        layout.addWidget(font_group)
        layout.addStretch()
        
        widget.setLayout(layout)
        return widget
    
    def _create_build_tab(self):
        """Create build settings tab."""
        # Similar structure...
        pass
    
    def apply_settings(self):
        """Apply current settings."""
        # Update settings object
        self.settings.theme = self.theme_combo.currentText()
        self.settings.font_size = self.font_size_spin.value()
        self.settings.bold_font = self.bold_check.isChecked()
        
        # Save to disk
        save_settings(self.settings)
        
        # Emit signal or call parent method
        if self.parent():
            self.parent().apply_settings()
    
    def get_settings(self) -> AppSettings:
        """Get modified settings."""
        return self.settings

Applying Settings

File: src/cpplab/app.py

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        # Load settings on startup
        self.settings = load_settings()
        self.apply_settings()
    
    def apply_settings(self):
        """Apply current settings to UI."""
        # Theme
        if self.settings.theme in THEMES:
            self.setStyleSheet(THEMES[self.settings.theme])
        
        # Font
        font = QFont("Consolas", self.settings.font_size)
        if self.settings.bold_font:
            font.setBold(True)
        
        self.editor.setFont(font)
        self.buildOutputEdit.setFont(font)
        self.problemsTextEdit.setFont(font)
        self.consoleTextEdit.setFont(font)
        
        # Editor settings
        tab_width = self.settings.tab_width * 10  # Pixels
        self.editor.setTabStopDistance(tab_width)
        
        # Show/hide line numbers
        if self.settings.show_line_numbers:
            # Enable line numbers
            pass
    
    def show_settings_dialog(self):
        """Show settings dialog."""
        dialog = SettingsDialog(self.settings, self)
        
        if dialog.exec() == QDialog.DialogCode.Accepted:
            # Get updated settings
            self.settings = dialog.get_settings()
            save_settings(self.settings)
            
            # Apply changes
            self.apply_settings()

Themes

Built-in Themes

Classic Theme:

THEMES = {
    "classic": """
        QMainWindow {
            background-color: #f0f0f0;
        }
        QMenuBar {
            background-color: #ffffff;
            border-bottom: 1px solid #c0c0c0;
        }
        QTextEdit {
            background-color: #ffffff;
            color: #000000;
            border: 1px solid #c0c0c0;
        }
        QPushButton {
            background-color: #e1e1e1;
            color: #000000;
            border: 1px solid #adadad;
            padding: 5px 10px;
            border-radius: 3px;
        }
        QPushButton:hover {
            background-color: #d0d0d0;
        }
        QStatusBar {
            background-color: #007acc;
            color: #ffffff;
        }
    """
}

Sky Blue Theme:

THEMES["sky_blue"] = """
    QMainWindow {
        background-color: #e6f2ff;
    }
    QMenuBar {
        background-color: #cce0ff;
        border-bottom: 1px solid #99c2ff;
    }
    QTextEdit {
        background-color: #f0f8ff;
        color: #003366;
        border: 1px solid #99c2ff;
    }
    QPushButton {
        background-color: #4a90d9;
        color: #ffffff;
        border: none;
        padding: 5px 10px;
        border-radius: 3px;
    }
    QPushButton:hover {
        background-color: #5fa3e8;
    }
    QStatusBar {
        background-color: #2a5a8a;
        color: #ffffff;
    }
"""

Custom Themes (Future)

User-Defined Themes:

{
  "theme": "custom",
  "custom_theme_path": "C:/Users/User/.cpplab/themes/my_theme.qss"
}

Theme File (my_theme.qss):

QMainWindow {
    background-color: #282c34;
}
QTextEdit {
    background-color: #1e2127;
    color: #abb2bf;
}

Project Settings

Location

Project Settings File:

<project_root>/cpplab_project.json

Example:

{
  "name": "MyApp",
  "language": "cpp",
  "standard": "c++17",
  "project_type": "console",
  "toolchain": "mingw64",
  "compile_flags": ["-Wall", "-Wextra"],
  "link_flags": [],
  "sources": ["src/main.cpp"]
}

Project vs User Settings

User Settings (global):

  • Theme
  • Font
  • Default toolchain
  • Default standards
  • Editor preferences

Project Settings (per-project):

  • Project name
  • Language
  • Standard (override user default)
  • Toolchain (override user default)
  • Compile/link flags
  • Source files

Priority: Project settings override user settings

Reset to Defaults

Method 1: Settings Dialog

Settings → Advanced → [Reset to Defaults] button

Method 2: Delete Settings File

Windows:

del C:\Users\<Username>\.cpplab\settings.json

Linux/macOS:

rm ~/.cpplab/settings.json

On Next Launch: Default settings used

Method 3: Code

# Reset to defaults
settings = AppSettings()
save_settings(settings)

Migration

Settings Version

Future-Proofing:

{
  "version": 1,
  "theme": "classic",
  ...
}

Upgrade Path

def load_settings() -> AppSettings:
    """Load settings with version migration."""
    settings_path = get_settings_path()
    
    if not settings_path.exists():
        return AppSettings()
    
    with open(settings_path, 'r') as f:
        data = json.load(f)
    
    # Check version
    version = data.get("version", 0)
    
    if version == 0:
        # Migrate from v0 to v1
        data = migrate_v0_to_v1(data)
    
    return AppSettings(**data)

Next: Performance and Benchmarks
Previous: UI Framework and PyQt6

Clone this wiki locally