# Contributing - [Issues](#issues) - [Pull Requests](#pull-requests) - [Procedure](#procedure) - [Commit Guidelines](#commit-guidelines) - [Coding Conventions](#coding-conventions) - [General](#general) - [Python](#python) - [QML](#qml) - [C++](#c) - [Resources](#resources) - [Packaging](#packaging) ## Issues [Issues](https://gitlab.com/mx-moment/moment/-/issues) on GitLab should be used to ask questions, report problems, request new features, or discuss potential changes before creating pull requests. Note that it is possible to [sign in with your GitHub account](https://gitlab.com/users/sign_in). Before opening new issues, please search for any already open or closed issue related to your problem, in order to prevent duplicates. You can also join us in the [#moment-client:matrix.org](https://matrix.to/#/%23moment-client:matrix.org) room for questions and discussions. ## Pull Requests For changes outside of simple bug/typo/formatting fixes, it is strongly recommended to first discuss your ideas in a related issue or in [#moment-client:matrix.org](https://matrix.to/#/%23moment-client:matrix.org). By sending your changes, you agree to license them under the LGPL 3.0 or later. ### Procedure Start by forking the main repository from GitLab, then clone your fork where you will make your changes: ```sh git clone --recursive https://gitlab.com/yourUsername/moment cd moment git remote add upstream https://gitlab.com/mx-moment/moment git fetch upstream git checkout -b example-branch-name ``` Test and commit your changes according to the [commit guidelines](#commit-guidelines), and `git push` to your fork's repo. You will then be able to make a pull request by going to the [main repo](https://gitlab.com/mx-moment/moment). Once your pull request is merged, you can update `main`, and delete your GitLab and local branch: ```sh git fetch upstream git checkout upstream/main git push -d origin example-branch-name git branch -d example-branch-name ``` Make sure `main` is up-to-date before creating new branches based on it. ## Commit Guidelines Commit messages should be made in this form: ``` Title, a short summary of the changes The body, a more detailed summary needed depending on the changes. Explain the goal of the code, how to reproduce the bug it solves (if this is a bug fix), any special reasoning behind the implementation or side-effects. ``` - Write informative titles, e.g. `TextField: fix copying selected text by Ctrl+C` instead of `fix field bug` (assuming `TextField` was the name of the component affected by the bug) - Write the title in imperative form and without a period at the end, e.g. `Fix thing` instead of `Fixed thing` or `Fixes thing.` - The title must not exceed 50 characters - A blank line is required between the first line summary and detailed body, if there is one - Lines of the body must not exceed 72 characters - Split independent changes into separate commits, don't combine fixes for different problems or add multiple systems forming a complex feature all at once - Every commit should be able to build and run the application without obvious crashes or tracebacks - Check for linter errors before committing by running `make test` in the repository's root. The test tools can be installed with `pip3 install --user -Ur requirements-dev.txt`. - For changes that aren't yet merged in a branch of the main repo, prefer amending or editing previous commits via git interactive rebase, rather than adding new "fix this" commits. This helps keeping the history clean. ## Coding Conventions ### General - Use four space indentations, no tabs - Use double quotes for strings, unless single quotes would avoid having to escape double quotes in the text - Keep lines under 80 columns, the only exception for this is long URL links that can't be broken in multiple parts - Keep lines free from any trailing whitespace - Function definitions, calls, list/dict/etc not fitting in one line follow this format (notice the trailing comma on the last element): ```python3 long_function_call( long_argument_1, long_argument_1, long_argument_3, long_argument_4, ) very_long_list_def = [ "Lorem ipsum dolor sit amet, consectetuer adipiscing elit", "Aenean massa. Cum sociis natoque penatibus", "Mus donec quam felis, ultricies nec, pellentesque", ] ``` - When creating new files, don't forget the copyright and license header you see in other files of the same language. ### Python - All functions, class attributes or top-level variables should have type hints - Separate all top-level classes and functions by two blank lines. For classes with many long methods, separate those methodes by two blank lines too. - Readability is important. Vertically-align consecutive lines of assignments, function definition arguments, dictionaries and inline comments: ```python3 # Bad: num: int = 1 # A comment args: List[str] = ["a", "b"] # Another comment def func( self, example_argument: int = 300, # Comment other: str = "Sample text", # Other comment some_floats: Tuple[float, float, float] = (4.2, 1.1, 9.8), ) -> None: pass # Good: num: int = 1 # A comment args: List[str] = ["a", "b"] # Another comment def func( self, example_arg: int = 300, # Comment other: str = "Sample text", # Other comment some_floats: Tuple[float, float] = (4.2, 9.8), ) -> None: pass ``` If this is annoying, consider getting a plugin for your editor to automate it (e.g. [EasyAlign](https://github.com/junegunn/vim-easy-align) for vim). - Use f-strings as long as the readability isn't impacted. For more complex string formatting, use the shorter `%` syntax when features special to `str.format()` aren't needed. - Otherwise, follow the [PEP-8 standard](https://www.python.org/dev/peps/pep-0008/) ### QML - Don't add trailing semicolons to lines - If an object has more than one property, always keep each property on their own line: ```qml Rectangle { x: 10; width: 100; height: width; color: "black" } // Bad! Rectangle { // Good x: 10 width: 100 height: width color: "black" } ``` - When creating new files, the `id` for the root component should always be `root` - When writing new code, refer to parent object properties explicitely, e.g. `parent.prop_name` or `someId.prop_name` instead of just `` - Don't use [States](https://doc.qt.io/qt-5/qml-qtquick-state.html), the Rectangle in the description's example could simply be written like this: ```qml Rectangle { width: 100 height: 100 color: mouseArea.containsPress ? "red" : "black" MouseArea { id: mouseArea anchors.fill: parent } } ``` - Otherwise, follow the [QML Coding Conventions](https://doc.qt.io/qt-5/qml-codingconventions.html) ### C++ - Add C++ only if it can't easily be done in QML or Python; or if doing it in Python requires adding a dependency while a similar feature is already provided by Qt, feature that just needs to be exposed with some wrapper code ([example](https://gitlab.com/mx-moment/moment/blob/v0.6.4/src/utils.h#L31)). - Be explicit, always use `this->` to refer to methods and class attributes - Don't split modules between `.h` and `.cpp` files, this creates unnecessary code repetition and has no benefits when most methods will contain very few lines and the module is only included once before starting the GUI. ## Resources Resources include background images, icons or sounds. New resources must have a permissive license that does not require attribution. Built-in icons must be in the SVG format. The majority of icons used in the application come from [iconmonstr](https://iconmonstr.com). When possible without any noticable quality loss, reduce the size of resources and strip any metadata by using tools such as: - `svgcleaner --allow-bigger-file --indent 4 ` for SVG images - `pngquant --force --speed=1 --strip ` for PNG images - `jpegoptim --quality 80 --strip-all ` for JPEG images ## Packaging If a new package for a distribution or any other easy way of installing the application exists, [pull request](#pull-requests) for adding instructions to the [INSTALL.md](INSTALL.md) are welcome. Some suggestions when creating packages: - Among the dependencies from the `submodules` directory, `hsluv-c` is the only one that is still needed for building. The other folders are kept to allow building past versions of the application, and should be ignored.