Skip to content

Commit 0b4f365

Browse files
committed
feat(workspace): add multi-root workspace support (v0.2.0)
1 parent 439f001 commit 0b4f365

17 files changed

Lines changed: 1089 additions & 24 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Thumbs.db
3333
*.sqlite
3434
*.sqlite3
3535
*.log
36+
config/settings.json
3637
*.exe
3738
*.msi
3839
*.msix

CHANGELOG.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,41 @@
1010

1111
Alle wesentlichen Änderungen an CodeBox werden hier dokumentiert.
1212

13+
## [0.2.0] - 2026-09-12
14+
15+
### Multi-Root-Workspace Support
16+
17+
- `core/workspace.py`: Neues Kernmodul für Multi-Root-Arbeitsbereiche:
18+
- Datenklasse `WorkspaceFolder` (`path`, `name`, `to_dict`, `from_dict`) mit portabler relativer Pfadberechnung.
19+
- `WorkspaceManager` (`QObject`) mit Signalen `foldersChanged`, `activeFolderChanged(object)`, `workspaceLoaded(str)`.
20+
- Methoden `add_folder`, `remove_folder`, `set_active_folder`, `set_single_folder`, `clear`, `find_folder_for_file`.
21+
- Datei-Format `.codebox-workspace` (JSON) mit Metadaten, Schema-Version und relativer Pfadauflösung für geräteübergreifende Portabilität (OneDrive/Multi-Device).
22+
- Methode `collect_all_files` zum schnellen Ordner-übergreifenden Durchsuchen mit Filterregeln.
23+
- `features/project_view.py`:
24+
- Dynamischer Arbeitsbereich-Umschalter (`workspace_widget` mit `workspace_combo`, `btn_add_root`, `btn_remove_root`), der sich bei mehreren geöffneten Ordnern automatisch einblendet und bei Einzelordnern für ein aufgeräumtes Design unsichtbar bleibt.
25+
- Nahtloser Wechsel des aktiven Ordners und Aktualisierung von Git-Branch und Dateibaum.
26+
- Kontextmenü-Aktionen im Dateibaum für Verzeichnisse: "Ordner zum Arbeitsbereich hinzufügen" und "Ordner aus Arbeitsbereich entfernen".
27+
- `ui/main_window.py`:
28+
- Menü *Datei* erweitert um:
29+
- *Ordner öffnen...* (`Ctrl+Shift+O`): Öffnet einen Ordner als einzelnen Arbeitsbereich.
30+
- *Ordner zum Arbeitsbereich hinzufügen...*: Fügt einen weiteren Ordner hinzu.
31+
- *Arbeitsbereich öffnen...*: Lädt eine `.codebox-workspace` Konfiguration.
32+
- *Arbeitsbereich speichern unter...*: Speichert den aktuellen Arbeitsbereich inklusive aller Ordner.
33+
- *Arbeitsbereich schließen*: Schließt alle Ordner des aktuellen Arbeitsbereichs.
34+
- Intelligente Dateizuordnung (`_on_file_changed`): Erkennt automatisch, welchem Arbeitsbereichs-Ordner eine geöffnete Datei angehört, und wechselt den aktiven Ordner, ohne andere Arbeitsbereichs-Ordner zu verwerfen.
35+
- Automatische Synchronisation des integrierten Terminals auf den jeweils aktiven Arbeitsbereichs-Ordner.
36+
- `ui/command_palette.py`:
37+
- Quick-Open (`Ctrl+P`) durchsucht im Multi-Root-Modus alle Projektordner des Arbeitsbereichs gleichzeitig mit prägnanten Ordner-Badges (z. B. `[backend] api/routes.py`).
38+
- Neue Arbeitsbereichs-Aktionen stehen direkt über die Befehlspalette (`Ctrl+Shift+P`) zur Verfügung.
39+
- `config/__init__.py`:
40+
- Standardeinstellung `"recent_workspaces": []` hinzugefügt.
41+
- `ui/shortcuts_dialog.py`:
42+
- Shortcuts-Übersicht um die neuen Arbeitsbereichs-Aktionen und `Ctrl+Shift+O` ergänzt.
43+
- Testsuite:
44+
- `tests/test_workspace.py`: 5 Unit-Tests für `WorkspaceManager` und `WorkspaceFolder`.
45+
- `tests/test_multi_root_workspace.py`: 4 Integrations-Tests für UI, Lifecycle, Dateizuordnung und Quick-Open Suche.
46+
- 248 Tests bestanden, 1 übersprungen, 100% grün.
47+
1348
## [0.1.9] - 2026-09-11
1449

1550
### Zuschaltbarer Vim-Keybindings Modus

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
[![Python 3.10+](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://www.python.org/)
77
[![Platform: Windows | Linux | macOS](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)]()
88
[![CI](https://github.com/dev-bricks/CodeBox/actions/workflows/ci.yml/badge.svg)](https://github.com/dev-bricks/CodeBox/actions/workflows/ci.yml)
9-
[![Tests](https://img.shields.io/badge/tests-239%20passed%20%7C%20100%25-brightgreen.svg)]()
9+
[![Tests](https://img.shields.io/badge/tests-248%20passed%20%7C%20100%25-brightgreen.svg)]()
1010
[![Privacy: Zero-Egress](https://img.shields.io/badge/privacy-100%25%20local--first%20%7C%20zero--egress-success.svg)](SECURITY.md)
1111
[![Security Policy](https://img.shields.io/badge/security-bilingual%20policy-blue.svg)](SECURITY.md)
1212
[![Ecosystem: dev-bricks](https://img.shields.io/badge/ecosystem-dev--bricks-blue.svg)](https://github.com/dev-bricks)
1313
[![Part of: open-bricks](https://img.shields.io/badge/part%20of-open--bricks-blue.svg)](https://github.com/open-bricks)
1414
[![LSP Ready](https://img.shields.io/badge/LSP-ready-purple.svg)]()
15-
[![Version: 0.1.9](https://img.shields.io/badge/version-0.1.9-green.svg)](CHANGELOG.md)
15+
[![Version: 0.2.0](https://img.shields.io/badge/version-0.2.0-green.svg)](CHANGELOG.md)
1616
[![llms.txt](https://img.shields.io/badge/llms.txt-available-green.svg)](llms.txt)
1717

1818
[Deutsch](README_de.md) | English

README_de.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
[![Python 3.10+](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue.svg)](https://www.python.org/)
77
[![Plattform: Windows | Linux | macOS](https://img.shields.io/badge/platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)]()
88
[![CI](https://github.com/dev-bricks/CodeBox/actions/workflows/ci.yml/badge.svg)](https://github.com/dev-bricks/CodeBox/actions/workflows/ci.yml)
9-
[![Tests](https://img.shields.io/badge/tests-239%20passed%20%7C%20100%25-brightgreen.svg)]()
9+
[![Tests](https://img.shields.io/badge/tests-248%20passed%20%7C%20100%25-brightgreen.svg)]()
1010
[![Datenschutz: Zero-Egress](https://img.shields.io/badge/datenschutz-100%25%20local--first%20%7C%20zero--egress-success.svg)](SECURITY.md)
1111
[![Sicherheitsrichtlinie](https://img.shields.io/badge/sicherheit-zweisprachige%20policy-blue.svg)](SECURITY.md)
1212
[![Ökosystem: dev-bricks](https://img.shields.io/badge/ecosystem-dev--bricks-blue.svg)](https://github.com/dev-bricks)
1313
[![Dachverband: open-bricks](https://img.shields.io/badge/part%20of-open--bricks-blue.svg)](https://github.com/open-bricks)
1414
[![LSP Ready](https://img.shields.io/badge/LSP-ready-purple.svg)]()
15-
[![Version: 0.1.9](https://img.shields.io/badge/version-0.1.9-green.svg)](CHANGELOG.md)
15+
[![Version: 0.2.0](https://img.shields.io/badge/version-0.2.0-green.svg)](CHANGELOG.md)
1616
[![llms.txt](https://img.shields.io/badge/llms.txt-verf%C3%BCgbar-green.svg)](llms.txt)
1717

1818
[English](README.md) | Deutsch

config/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"auto_save": False,
1212
"show_minimap": True,
1313
"recent_files": [],
14+
"recent_workspaces": [],
1415
"vim_mode": False
1516
}
1617

core/vim_mode.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from __future__ import annotations
1717

1818
from enum import Enum
19-
from typing import Optional, Tuple, TYPE_CHECKING
19+
from typing import Tuple, TYPE_CHECKING
2020
from PySide6.QtCore import QObject, Signal, Qt
2121
from PySide6.QtGui import (
2222
QTextCursor, QKeyEvent, QGuiApplication, QFontMetrics
@@ -146,7 +146,6 @@ def set_mode(self, mode: VimMode):
146146
self._mode = mode
147147
return
148148

149-
old_mode = self._mode
150149
self._mode = mode
151150
self.reset_buffers()
152151

0 commit comments

Comments
 (0)