Welcome to the Photon Development Team.
This document outlines the standards for contributing to Photon. As a high-performance graphics application, strict adherence to memory management, threading safety, and architectural boundaries is required.
We follow a Feature-Branch Workflow. Direct commits to main are forbidden.
- master: The stable production branch. Must always compile and launch. Only humans merge code here!!!
- develop: The stable develop branch where all the features get merged. Agents can merge code here.
- feat/<name>: For new features (e.g., feat/histogram, feat/raw-loader).
- fix/<name>: For bug fixes (e.g., fix/memory-leak-raw).
- refactor/<name>: For code cleanup without behavior changes.
We use Conventional Commits to generate changelogs automatically.
- feat: ... -> Adds functionality (e.g., feat: implement exposure slider logic)
- fix: ... -> Fixes a bug (e.g., fix: resolve segfault on app exit)
- chore: ... -> Maintenance (e.g., chore: update CMake version)
- perf: ... -> Performance improvements (e.g., perf: move raw unpacking to worker thread)
Ensure your local environment does not pollute the repo.
# Build directories
build/
bin/
*.o
*.obj
# Qt Generated
moc_*
qrc_*
ui_*
Makefile
cmake_install.cmake
CMakeCache.txt
# IDEs
.vscode/
.idea/
*.userSince Photon is a hybrid C++/QML application, we test the "Brains" (C++) and the "Face" (QML) separately.
- Framework: QtTest (Native integration with QObjects).
- Location: tests/auto/
- Rule: Every major Engine feature (Raw Loading, Math operations) must have a unit test.
- Command: ctest (via CMake).
Example Test Case (TestRawEngine.cpp):
void TestRawEngine::testLoadInvalidFile() {
RawEngine engine;
bool success \= engine.loadFile("non_existent.arw");
QVERIFY(success \== false);
}- Framework: Qt Quick Test
- Location: tests/qml/
- Rule: Test standard user flows (e.g., "Clicking Export emits the export signal").
- Since this is a graphics app, automated tests cannot easily verify "Does the image look correct?".
- Rule: Before merging a PR, run the app and visually confirm:
- The UI scales correctly (resize window).
- No visual artifacts in the Viewport.
- Console output is clean of ReferenceError or Binding loop detected.
- Standard: C++17.
- Memory Management:
- Strict RAII: Never use new without an immediate owner. Use std::unique_ptr or std::shared_ptr.
- Qt Ownership: If a generic QObject has a parent, standard pointers are acceptable (Qt deletes children automatically).
- Pointers: Always initialize raw pointers to nullptr.
- Headers: Use #pragma once.
- Includes: Order: Local ("RawEngine.h") -> Qt (<QImage>) -> Std (<vector>).
- Formatting: Use clang-format (Google style or Qt style).
- Ids: Use id: root for the top-level item of a component. Use descriptive ids for children (id: submitButton).
- Property Bindings: PREFER bindings (width: parent.width * 0.5) over imperative assignment (Component.onCompleted: width = ...).
- Signal Handlers: Use arrow functions for short logic: onClicked: (mouse) => root.process(mouse)
- No Magic Numbers: Use Theme.spacing, Theme.color, etc. Do not hardcode 10px or #ffffff.
Photon is a Real-Time application. Latency is the enemy.
- The "16ms" Rule: Never block the Main Thread (GUI Thread) for more than 16ms.
- Bad: rawProcessor.process() (runs on main thread).
- Good: QtConcurrent::run(...) or a dedicated WorkerThread.
- Texture Uploads:
- Upload textures to GPU only when changed.
- Reuse QSGTexture objects; do not delete and new them every frame.
- QML Complexity:
- Avoid complex JavaScript in onPaint or property bindings that trigger every frame.
- Use Item.visible: false instead of opacity: 0 (save rendering cost).
A feature is considered "Done" only when:
- It builds without warnings on Linux (GCC).
- Unit tests pass (ctest).
- No memory leaks detected (Run with valgrind periodically).
- Code is formatted (clang-format).
- Commit history is clean and squashed if necessary.