|
| 1 | +# WARP.md |
| 2 | + |
| 3 | +This file provides guidance to WARP (warp.dev) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +OpenCloud Desktop is a Qt-based C++ desktop synchronization client for OpenCloud, supporting Windows, macOS, and Linux. The project uses CMake as its build system and follows a modular architecture with separate libraries for sync logic, GUI, and platform-specific integrations. |
| 8 | + |
| 9 | +- **Framework**: Qt 6.8+ (Core, Widgets, Network, QML/Quick) |
| 10 | +- **Language**: C++20 |
| 11 | +- **Build System**: CMake 3.18+ with KDE ECM (Extra CMake Modules) |
| 12 | +- **Database**: SQLite3 |
| 13 | +- **Version**: 3.1.1 (see VERSION.cmake) |
| 14 | + |
| 15 | +## Build System & Development Commands |
| 16 | + |
| 17 | +### Building with Craft (Recommended) |
| 18 | + |
| 19 | +Craft is KDE's meta-build system that handles all dependencies automatically. This is the recommended approach for local development. |
| 20 | + |
| 21 | +#### Prerequisites |
| 22 | + |
| 23 | +```bash |
| 24 | +# Install PowerShell (required by Craft scripts) |
| 25 | +brew install powershell/tap/powershell |
| 26 | + |
| 27 | +# Clone CraftMaster (if not already present) |
| 28 | +mkdir -p ~/craft/CraftMaster |
| 29 | +git clone --depth=1 https://invent.kde.org/kde/craftmaster.git ~/craft/CraftMaster/CraftMaster |
| 30 | +``` |
| 31 | + |
| 32 | +#### Initial Craft Setup |
| 33 | + |
| 34 | +```bash |
| 35 | +# Set target architecture (use macos-clang-arm64 for Apple Silicon, macos-clang-x86_64 for Intel) |
| 36 | +export CRAFT_TARGET=macos-clang-arm64 |
| 37 | + |
| 38 | +# Initialize Craft |
| 39 | +pwsh .github/workflows/.craft.ps1 --setup |
| 40 | + |
| 41 | +# Unshelve cached dependency versions |
| 42 | +pwsh .github/workflows/.craft.ps1 -c --unshelve .craft.shelf |
| 43 | +pwsh .github/workflows/.craft.ps1 -c craft |
| 44 | + |
| 45 | +# Install project dependencies |
| 46 | +pwsh .github/workflows/.craft.ps1 -c --install-deps opencloud/opencloud-desktop |
| 47 | +``` |
| 48 | + |
| 49 | +#### Building the Application |
| 50 | + |
| 51 | +```bash |
| 52 | +export CRAFT_TARGET=macos-clang-arm64 |
| 53 | + |
| 54 | +# Point Craft to your local source directory |
| 55 | +pwsh .github/workflows/.craft.ps1 -c --set "srcDir=$(pwd)" opencloud/opencloud-desktop |
| 56 | + |
| 57 | +# Configure build options (optional - enables crash reporter, tests, shell integration) |
| 58 | +pwsh .github/workflows/.craft.ps1 -c --set 'args=-DWITH_CRASHREPORTER=ON -DCRASHREPORTER_SUBMIT_URL=http://localhost:8080/submit -DBUILD_TESTING=ON -DBUILD_SHELL_INTEGRATION=ON' opencloud/opencloud-desktop |
| 59 | + |
| 60 | +# Build with max parallelism |
| 61 | +export MAKEFLAGS="-j$(sysctl -n hw.ncpu)" |
| 62 | +export CMAKE_BUILD_PARALLEL_LEVEL=$(sysctl -n hw.ncpu) |
| 63 | +pwsh .github/workflows/.craft.ps1 -c --no-cache opencloud/opencloud-desktop |
| 64 | +``` |
| 65 | + |
| 66 | +#### Running the Built Application |
| 67 | + |
| 68 | +```bash |
| 69 | +# macOS |
| 70 | +open ~/Documents/craft/macos-clang-arm64/Applications/KDE/OpenCloud.app |
| 71 | +``` |
| 72 | + |
| 73 | +#### Running Tests |
| 74 | + |
| 75 | +```bash |
| 76 | +export CRAFT_TARGET=macos-clang-arm64 |
| 77 | +pwsh .github/workflows/.craft.ps1 -c --no-cache --test opencloud/opencloud-desktop |
| 78 | +``` |
| 79 | + |
| 80 | +#### Rebuilding After Changes |
| 81 | + |
| 82 | +```bash |
| 83 | +export CRAFT_TARGET=macos-clang-arm64 |
| 84 | +pwsh .github/workflows/.craft.ps1 -c --no-cache opencloud/opencloud-desktop |
| 85 | +``` |
| 86 | + |
| 87 | +### Alternative: Plain CMake (Advanced) |
| 88 | + |
| 89 | +For development without Craft, you must manually install all dependencies first: |
| 90 | + |
| 91 | +### Running Tests |
| 92 | + |
| 93 | +Tests use Qt Test framework via ECM's `ecm_add_tests`: |
| 94 | + |
| 95 | +```bash |
| 96 | +# From build directory |
| 97 | +ctest |
| 98 | + |
| 99 | +# Run specific test |
| 100 | +ctest -R testname |
| 101 | + |
| 102 | +# Run tests with verbose output |
| 103 | +ctest -V |
| 104 | + |
| 105 | +# Run single test binary directly |
| 106 | +./bin/testsyncengine |
| 107 | +``` |
| 108 | + |
| 109 | +Test binaries are located in `build/bin/` and follow the naming pattern `test<classname>` (e.g., `testsyncengine`, `testsyncmove`). |
| 110 | + |
| 111 | +### Code Quality |
| 112 | + |
| 113 | +```bash |
| 114 | +# QML formatting (requires qttools) |
| 115 | +qmlformat -i <file.qml> |
| 116 | + |
| 117 | +# C++ formatting (requires clang-format) |
| 118 | +clang-format -i <file.cpp> |
| 119 | + |
| 120 | +# The project has pre-commit hooks for formatting (requires ECM 5.79+) |
| 121 | +``` |
| 122 | + |
| 123 | +### Build Options |
| 124 | + |
| 125 | +Key CMake options (set via `-D<OPTION>=ON/OFF`): |
| 126 | + |
| 127 | +- `BUILD_TESTING`: Enable test building (default: OFF, set to ON for development) |
| 128 | +- `WITH_CRASHREPORTER`: Build crash reporter component (requires CRASHREPORTER_SUBMIT_URL) |
| 129 | +- `BUILD_SHELL_INTEGRATION`: Build shell integration (macOS only, default: ON) |
| 130 | +- `WITH_AUTO_UPDATER`: Enable auto-updater component (default: OFF) |
| 131 | +- `BETA_CHANNEL_BUILD`: Use standalone profile for beta releases (default: OFF) |
| 132 | +- `FORCE_ASSERTS`: Build with -DQT_FORCE_ASSERTS (default: OFF) |
| 133 | +- `VIRTUAL_FILE_SYSTEM_PLUGINS`: Specify VFS plugins (default: "off cfapi") |
| 134 | + |
| 135 | +## Code Architecture |
| 136 | + |
| 137 | +### High-Level Structure |
| 138 | + |
| 139 | +``` |
| 140 | +src/ |
| 141 | +├── libsync/ # Core synchronization library (platform-independent) |
| 142 | +├── gui/ # Qt GUI application and QML interface |
| 143 | +├── cmd/ # Command-line interface |
| 144 | +├── crashreporter/ # Crash reporting (optional) |
| 145 | +├── plugins/vfs/ # Virtual File System plugins |
| 146 | +└── resources/ # QRC files, icons, QML resources |
| 147 | +``` |
| 148 | + |
| 149 | +### Key Components |
| 150 | + |
| 151 | +#### 1. Sync Engine (`libsync/`) |
| 152 | + |
| 153 | +The core synchronization logic resides in `libsync`, which is built as a shared library (`OpenCloudLibSync`). |
| 154 | + |
| 155 | +**Central Classes**: |
| 156 | +- `SyncEngine`: Orchestrates the sync process (discovery → reconcile → propagation) |
| 157 | +- `OwncloudPropagator`: Manages propagation of sync operations via job system |
| 158 | +- `DiscoveryPhase`: Discovers local and remote changes |
| 159 | +- `SyncFileItem`: Represents a file/directory that needs syncing |
| 160 | +- `SyncJournalDb`: SQLite-based journal for tracking sync state |
| 161 | + |
| 162 | +**Job System**: |
| 163 | +- Base: `PropagatorJob` (abstract base for all jobs) |
| 164 | +- `PropagateItemJob`: Single-item operations (upload/download/delete) |
| 165 | +- `PropagatorCompositeJob`: Container for multiple jobs |
| 166 | +- Specific jobs: `PropagateDownload`, `PropagateUpload*`, `PropagateRemoteDelete`, `PropagateRemoteMove`, `PropagateRemoteMkdir` |
| 167 | + |
| 168 | +**Network Layer**: |
| 169 | +- `AbstractNetworkJob`: Base class for all network operations |
| 170 | +- `AccessManager`: Network access manager with logging and bandwidth management |
| 171 | +- Jobs in `networkjobs/`: `GetFileJob`, `JsonJob`, `SimpleNetworkJob`, etc. |
| 172 | + |
| 173 | +**Authentication**: |
| 174 | +- `CredentialManager`: Manages credentials via Qt6Keychain |
| 175 | +- `AbstractCredentials`: Base class for credential types |
| 176 | +- `OAuth`: OAuth2 flow implementation |
| 177 | +- `HttpCredentials`: HTTP-based authentication |
| 178 | + |
| 179 | +#### 2. GUI Layer (`gui/`) |
| 180 | + |
| 181 | +Built as a shared library (`OpenCloudGui`) with QML integration via ECM's QML module system. |
| 182 | + |
| 183 | +**Key Patterns**: |
| 184 | +- QML for UI (`qml/` subdirectories) |
| 185 | +- C++ models for data exposure to QML |
| 186 | +- Qt Widgets for legacy dialogs and settings |
| 187 | +- Platform-specific code: |
| 188 | + - macOS: `.mm` files (Objective-C++) |
| 189 | + - Windows: `_win.cpp` files |
| 190 | + - Linux: `_linux.cpp` / `_unix.cpp` files |
| 191 | + |
| 192 | +**Important Classes**: |
| 193 | +- `Application`: Main application controller |
| 194 | +- `AccountManager`: Manages multiple accounts |
| 195 | +- `FolderMan`: Manages sync folders |
| 196 | +- `Folder`: Represents a single sync folder |
| 197 | +- `SettingsDialog`: Main settings interface |
| 198 | + |
| 199 | +#### 3. Virtual File System (VFS) |
| 200 | + |
| 201 | +Plugin-based architecture for virtual files (on-demand file hydration): |
| 202 | + |
| 203 | +- Base: `src/libsync/vfs/` (abstract VFS interface) |
| 204 | +- Plugins: `src/plugins/vfs/` (platform-specific implementations) |
| 205 | +- Configured via `VIRTUAL_FILE_SYSTEM_PLUGINS` CMake variable |
| 206 | +- Plugin discovery via `OCAddVfsPlugin.cmake` |
| 207 | + |
| 208 | +#### 4. Platform Abstraction |
| 209 | + |
| 210 | +Platform-specific code is isolated via: |
| 211 | +- Compile-time selection in CMakeLists.txt |
| 212 | +- Platform files: `platform_win.cpp`, `platform_mac.mm`, `platform_unix.cpp` |
| 213 | +- `FileSystem` namespace for cross-platform file operations |
| 214 | + |
| 215 | +### Dependencies |
| 216 | + |
| 217 | +**Required**: |
| 218 | +- Qt6 (Core, Concurrent, Network, Widgets, Xml, Quick, QuickControls2, LinguistTools) |
| 219 | +- Qt6Keychain 0.13+ |
| 220 | +- SQLite3 3.9.0+ |
| 221 | +- ZLIB |
| 222 | +- ECM 6.0.0+ (KDE Extra CMake Modules) |
| 223 | +- LibreGraphAPI 1.0.4+ (Libre Graph API client) |
| 224 | +- KDSingleApplication-qt6 1.0.0+ |
| 225 | + |
| 226 | +**Optional**: |
| 227 | +- Sparkle (macOS auto-updater) |
| 228 | +- AppImageUpdate (Linux AppImage updater) |
| 229 | +- Inotify (Linux file watching) |
| 230 | +- CrashReporterQt (crash reporting) |
| 231 | +- LibSnoreToast (Windows notifications) |
| 232 | + |
| 233 | +**Platform-Specific**: |
| 234 | +- macOS: CoreServices, Foundation, AppKit, IOKit frameworks |
| 235 | +- Linux: Qt6::DBus for notifications |
| 236 | +- Windows: NSIS (installer packaging) |
| 237 | + |
| 238 | +### Build Artifacts |
| 239 | + |
| 240 | +- Main executable: `opencloud` (or `opencloud_beta` for beta builds) |
| 241 | +- Libraries: `libOpenCloudLibSync.so/dylib/dll`, `libOpenCloudGui.so/dylib/dll` |
| 242 | +- Tests: `build/bin/test*` (e.g., `testsyncengine`, `testdownload`) |
| 243 | + |
| 244 | +## Development Notes |
| 245 | + |
| 246 | +### Adding Tests |
| 247 | + |
| 248 | +Tests use a custom `opencloud_add_test()` function defined in `test/opencloud_add_test.cmake`: |
| 249 | + |
| 250 | +```cmake |
| 251 | +opencloud_add_test(MyNewFeature) |
| 252 | +``` |
| 253 | + |
| 254 | +This expects a source file `test/testmynewfeature.cpp` with a Qt Test class. The test automatically links against `OpenCloudGui`, `syncenginetestutils`, `testutilsloader`, and `Qt::Test`. |
| 255 | + |
| 256 | +### Working with QML |
| 257 | + |
| 258 | +QML modules are defined using ECM's `ecm_add_qml_module`: |
| 259 | + |
| 260 | +```cmake |
| 261 | +ecm_add_qml_module(targetname |
| 262 | + URI eu.OpenCloud.modulename |
| 263 | + VERSION 1.0 |
| 264 | + NAMESPACE OCC |
| 265 | + QML_FILES qml/MyComponent.qml |
| 266 | +) |
| 267 | +``` |
| 268 | + |
| 269 | +### Shell Integration |
| 270 | + |
| 271 | +Separate from main client (see PACKAGING.md): |
| 272 | +- [dolphin plugin](https://github.com/opencloud-eu/desktop-shell-integration-dolphin) |
| 273 | +- [nautilus/caja plugin](https://github.com/opencloud-eu/desktop-shell-integration-nautilus) |
| 274 | +- [resources](https://github.com/opencloud-eu/desktop-shell-integration-resources) |
| 275 | + |
| 276 | +Designed for distro packaging to decouple client releases from shell integration. |
| 277 | + |
| 278 | +### Debugging |
| 279 | + |
| 280 | +- All QDebug output can be redirected to log window/file (disable via `NO_MSG_HANDLER=ON`) |
| 281 | +- Test environment variables set automatically: `QT_QPA_PLATFORM=offscreen` on Linux/Windows |
| 282 | +- Force assertions in tests: `QT_FORCE_ASSERTS` is always defined for test targets |
| 283 | + |
| 284 | +### CI/CD |
| 285 | + |
| 286 | +GitHub Actions workflow (`.github/workflows/main.yml`) uses: |
| 287 | +- **Craft** (KDE's meta build system) for dependency management |
| 288 | +- Matrix builds: Windows (MSVC), macOS (Clang/ARM64), Linux (GCC/AppImage) |
| 289 | +- Automated: QML format linting, clang-format linting, clang-tidy analysis |
| 290 | +- Tests run on all platforms via `craft --test` |
| 291 | + |
| 292 | +### Crash Reporter Development |
| 293 | + |
| 294 | +A simple Python crash report server is provided for local development: |
| 295 | + |
| 296 | +```bash |
| 297 | +# Start the crash report server (receives reports on port 8080) |
| 298 | +python3 tools/crash_server.py |
| 299 | + |
| 300 | +# Reports are saved to tools/crash_reports/ |
| 301 | +``` |
| 302 | + |
| 303 | +The server accepts multipart form data with crash dumps and metadata. |
| 304 | + |
| 305 | +### Craft Directory Structure |
| 306 | + |
| 307 | +When using Craft, files are organized as follows: |
| 308 | +- `~/craft/CraftMaster/` - CraftMaster scripts |
| 309 | +- `~/Documents/craft/macos-clang-arm64/` - Build root for macOS ARM64 |
| 310 | + - `Applications/KDE/OpenCloud.app` - Built application |
| 311 | + - `lib/` - Built libraries |
| 312 | + - `bin/` - Built executables and test binaries |
| 313 | +- `~/Documents/craft/downloads/` - Downloaded source archives |
| 314 | +- `~/Documents/craft/blueprints/` - Craft package definitions |
| 315 | + |
| 316 | +## Common Patterns |
| 317 | + |
| 318 | +- **Logging**: Use Qt logging categories (e.g., `Q_DECLARE_LOGGING_CATEGORY(lcSync)`) |
| 319 | +- **Export macros**: `OPENCLOUD_SYNC_EXPORT` (libsync), `OPENCLOUD_GUI_EXPORT` (gui) |
| 320 | +- **Branding**: Configured via `OPENCLOUD.cmake` and `THEME.cmake` |
| 321 | +- **Error handling**: `SyncFileItem::Status` enum for operation results |
| 322 | +- **Async operations**: Qt signal/slot pattern, job-based architecture |
| 323 | +- **Config management**: `ConfigFile` class wraps QSettings |
| 324 | + |
| 325 | +## Localization |
| 326 | + |
| 327 | +Translation files in `translations/desktop_*.ts` (Qt Linguist format). Supported languages: ar, de, en, fr, it, ko, nl, pt, ru, sv. |
0 commit comments