diff --git a/.github/workflows/deploy-dev-docs.yml b/.github/workflows/deploy-dev-docs.yml new file mode 100644 index 00000000..57a3635a --- /dev/null +++ b/.github/workflows/deploy-dev-docs.yml @@ -0,0 +1,75 @@ +name: Deploy developer docs + +on: + push: + branches: [ master, docs ] + paths: + - 'src/**' + - 'docs/dev/**' + - '.github/workflows/deploy-dev-docs.yml' + +jobs: + build-and-deploy: + runs-on: ubuntu-22.04 + steps: + - name: Install dependencies + run: | + sudo apt-get --yes --quiet update + sudo apt-get --yes --no-install-recommends install doxygen + pip install \ + mkdocs \ + mkdocs-material \ + git+https://github.com/veracioux/mkdoxy@v1.0.0 + + - name: Checkout flameshot source + uses: actions/checkout@v3 + with: + path: 'flameshot' + + - name: Build docs + working-directory: ${{github.workspace}}/flameshot/docs/dev + run: | + make build + + - name: Checkout flameshot website + uses: actions/checkout@v3 + with: + repository: 'flameshot-org/flameshot-org.github.io' + ref: 'gh-pages' + path: 'website' + + - name: Configure git credentials for website repo + working-directory: ${{github.workspace}}/website + run: | + git config user.name "GitHub Actions" + git config user.email "github-actions-bot@users.noreply.github.com" + git config http.https://github.com/.extraheader 'AUTHORIZATION basic ${{secrets.TOKEN_PUSH_TO_WEBSITE_REPO}}' + git remote add destination "https://x-access-token:${{secrets.TOKEN_PUSH_TO_WEBSITE_REPO}}@github.com/flameshot-org/flameshot-org.github.io" + + - name: Add developer docs to website deployment + working-directory: ${{github.workspace}}/website + run: | + # Create empty dev-docs-staging branch + git checkout --orphan dev-docs-staging + git rm -r --cached . + rm -rf docs/dev + # Copy generated docs over + mkdir -p docs + mv "${{github.workspace}}/flameshot/docs/dev/output" \ + "./docs/dev" + # Commit docs/dev to the dev-docs-staging branch + git add docs/dev + HASH="$(git --git-dir="${{github.workspace}}/flameshot/.git" rev-parse HEAD)" + git commit --message "Add developer docs from flameshot@$HASH" + # Apply changes to gh-pages + git checkout --force gh-pages + git checkout dev-docs-staging -- docs/dev + # Commit (we use `|| true` because the commit could be empty and thus fail) + git commit --message "Add developer docs from flameshot@$HASH" || true + + - name: Push to website repo + working-directory: ${{github.workspace}}/website + run: | + git push --force destination dev-docs-staging + git push destination gh-pages + diff --git a/.gitignore b/.gitignore index 8fbdd26a..389bcb5c 100644 --- a/.gitignore +++ b/.gitignore @@ -72,3 +72,6 @@ data/flatpak/.flatpak-builder #MacOS Crap .DS_Store + +# Miscellaneous +!docs/dev/Makefile diff --git a/docs/dev/.gitignore b/docs/dev/.gitignore new file mode 100644 index 00000000..90551e8b --- /dev/null +++ b/docs/dev/.gitignore @@ -0,0 +1,2 @@ +output +mkdoxy-generated diff --git a/docs/dev/Makefile b/docs/dev/Makefile new file mode 100644 index 00000000..f44e4321 --- /dev/null +++ b/docs/dev/Makefile @@ -0,0 +1,9 @@ +serve: + mkdocs serve --dev-addr localhost:8080 --watch ../../src +build: + mkdocs build + @echo "Post-processing..." + @bash post-process.sh + @echo "DONE." +clean: + rm -rf mkdoxy-generated output diff --git a/docs/dev/mkdocs.yml b/docs/dev/mkdocs.yml new file mode 100644 index 00000000..ad981543 --- /dev/null +++ b/docs/dev/mkdocs.yml @@ -0,0 +1,47 @@ +site_name: Flameshot Developer Docs +site_url: https://flameshot.org/docs/dev/ +repo_url: https://github.com/flameshot-org/flameshot/ +edit_uri: tree/master/docs/dev/src +docs_dir: src +site_dir: output +markdown_extensions: + - admonition + - attr_list + - toc: + permalink: "#" + - pymdownx.emoji: + emoji_index: !!python/name:materialx.emoji.twemoji + emoji_generator: !!python/name:materialx.emoji.to_svg + +plugins: + - search + - mkdoxy: + projects: + flameshot: + src-dirs: ../../src/ + full-doc: True + doxy-cfg: + FILE_PATTERNS: "*.cpp *.h" + # #TODO for some reason this causes an exception + EXCLUDE_PATTERNS: "*/capturetool.h" + FULL_PATH_NAMES: "NO" + SHOW_USED_FILES: "NO" + RECURSIVE: True + + save-api: mkdoxy-generated + debug: True + ignore-errors: False + +theme: + name: material + logo: https://flameshot.org/flameshot-icon.svg + +nav: + - Overview: index.md + - Debugging: debugging.md + - FAQ: faq.md + - 'Maintaining the documentation': docs.md + - API: + - Classes: flameshot/classes.md + - 'Class Hierarchy': flameshot/hierarchy.md + - Files: flameshot/files.md diff --git a/docs/dev/post-process.sh b/docs/dev/post-process.sh new file mode 100644 index 00000000..b9c5edbd --- /dev/null +++ b/docs/dev/post-process.sh @@ -0,0 +1,19 @@ +# Only run this script from the Makefile + +shopt -s globstar +cd output + +# Classes backlink to the ClassList in their breadcrumbs. We use the ClassIndex +# instead. +rm -rf flameshot/annotated +ln -sf classes flameshot/annotated + +# Hide 'Edit this page button' from the auto-generated docs pages +# It would be better to change the button to link to the file on github, but +# it seems like too much work right now. +sed -i 's|title="Edit this page"|& style="display: none !important"|' flameshot/*/*.html + +# MkDoxy adds Qt classes into the class hierarchy. We don't want that. +sed -i 's|
  • class Q[^<]*
  • ||' flameshot/*/*.html + +# vim: filetype=bash diff --git a/docs/dev/src/debugging.md b/docs/dev/src/debugging.md new file mode 100644 index 00000000..25566977 --- /dev/null +++ b/docs/dev/src/debugging.md @@ -0,0 +1,16 @@ +# Debugging + +## `FLAMESHOT_DEBUG_CAPTURE` + +With this cmake variable set to `ON`, the flameshot capture GUI window won't bypass the +window manager. This allows you to manipulate the capture GUI window like any +other window while debugging. + +This can be useful if a debugging breakpoint is triggered while flameshot is in +full screen mode. Without this variable, you might have trouble inspecting the +code due to a frozen full-screen window. + +Usage: +```shell +cmake -DFLAMESHOT_DEBUG_CAPTURE=ON ... +``` diff --git a/docs/dev/src/docs.md b/docs/dev/src/docs.md new file mode 100644 index 00000000..c8d4c410 --- /dev/null +++ b/docs/dev/src/docs.md @@ -0,0 +1,141 @@ +# Maintaining the documentation + +The narrative documentation is written in markdown and built into HTML using +[MkDocs][mkdocs], particularly the [MkDocs material theme][mkdocs-material]. The +source code documentation is generated using Doxygen and adapted for MkDocs +using [MkDoxy][mkdoxy] (a tweaked custom fork of the original). The source code +of this documentation can be found [here][doc-source]. + +!!! tip + + In order to edit a page from the documentation, click the :material-pencil: + button in the top right corner of the page. Please note that this button + won't work within the API section of the documentation - the button is + removed from there during [post-processing][], but it will still be visible + when [serving the website locally][serving-locally]. + +## Serving locally +To serve the documentation locally, run the `make serve` target in the +`docs/dev` directory. The server is available at the port designated in the +output of the command. + +## Notes and conventions +- When you add new files or rename existing files or section names, be sure to + edit the `nav` property of [mkdocs.yml][mkdocs.yml]. +- Always insert links as [reference style + links][markdown:reference-style-links]. This will make the docs source code + more readable and make broken links more easily detectable and replaceable. + +### Post-processing +There are some tweaks we make to the generated HTML documentation. We do that in +the `make build` target, by running the [post-process.sh][post-process.sh] +script. To see what post-processing we do, see that file. + +For this reason, the version of the documentation served locally using `make +serve` will not match the generated HTML documentation 100%. But those +inconsistencies are few and minor. + +## Dependencies +```shell +pip install \ + mkdocs \ + mkdocs-material \ + git+https://github.com/veracioux/mkdoxy@v1.0.0 +``` + +!!! note + + We use a forked version of [mkdoxy][mkdoxy-original] that can be found + [here][mkdoxy], that fixes some annoying things from the original. + +## Deployment + +The developer documentation is served from the official Flameshot website +[flameshot.org][website]. Here's how. + +The official website itself is served from this [repo][website-repo]. That repo +contains the user documentation. It's deployed using GitHub pages -- the served +files can be found on the [gh-pages][] branch of that repo. This branch is +automatically created by the [build][website-build] workflow on master. + +To make the developer docs available on the official site, we use a custom +GitHub action called [deploy-dev-docs][] in the [flameshot][] repo. This action +will build and deploy this documentation into the `docs/dev` subdirectory of the +[gh-pages][] branch. + +### The deploy-dev-docs GitHub workflow + +This workflow checks out the flameshot website [repo][website-repo] and does the following: + +- Creates a clean [dev-docs-staging][] branch (we'll explain why, below). +- Generates the developer docs under `docs/dev` there and makes a commit +- Checks out the [gh-pages][] branch and makes the same commit there +- Force-pushes the dev-docs-staging branch to the website repo +- Pushes the gh-pages branch to the website repo + +Since the [gh-pages][] branch is re-created from scratch by the [website +deployment workflow][website-build], the commit that added the developer +documentation will be lost. That's why we have to re-apply the commit during the +[website deployment workflow][website-build] as well. **That is the reason why +we created the** [**dev-docs-staging**][dev-docs-staging] **branch in the first +place.** + +!!! note + + The deploy-dev-docs workflow is set to run on the `docs` branch as well as `master`. + This branch is used for debugging the developer docs and its associated + workflows, without polluting the `master` branch with unnecessary commits. + +#### Access tokens +In order to make changes to the [website repo][website-repo] from within a +workflow in the [flameshot repo][flameshot], the workflow needs to use an access +token, which it obtains from the `TOKEN_PUSH_TO_WEBSITE_REPO` secret. + +The following process was used to set it up: + +1. A flameshot organization member with write access must create a personal + access token (PAT) [here][PAT] with write access to the [website repo][website-repo]. +2. A secret named `TOKEN_PUSH_TO_WEBSITE_REPO` must be added to the + [flameshot][] repo and its value must be set to the PAT. This can be done + [here][action-secrets]. + +For best security practice, the token should be set to expire after some time +(currently ~6 months). The token can be regenerated without the need to recreate +it. After regeneration you will need to update the `TOKEN_PUSH_TO_WEBSITE_REPO` +secret, which can be done [here][edit-secret]. + +!!! tip + + The currently active PAT is owned by [veracioux][] and is set to expire on July + 31 2024. If you notice the token has expired, ask him to re-generate it. + + +[post-processing]: #post-processing +[serving-locally]: #serving-locally + + +[flameshot]: https://github.com/flameshot-org/flameshot +[website]: https://flameshot.org +[doc-source]: https://github.com/flameshot-org/flameshot/tree/master/docs/dev +[website-repo]: https://github.com/flameshot-org/flameshot-org.github.io +[gh-pages]: https://github.com/flameshot-org/flameshot-org.github.io/tree/gh-pages +[dev-docs-staging]: https://github.com/flameshot-org/flameshot-org.github.io/tree/dev-docs-staging +[action-secrets]: https://github.com/flameshot-org/flameshot/settings/secrets/actions +[edit-secret]: https://github.com/flameshot-org/flameshot/settings/secrets/actions/TOKEN_PUSH_TO_WEBSITE_REPO + + +[mkdocs.yml]: https://github.com/flameshot-org/flameshot/blob/master/docs/dev/mkdocs.yml +[post-process.sh]: https://github.com/flameshot-org/flameshot/blob/master/docs/dev/post-process.sh +[deploy-dev-docs]: https://github.com/flameshot-org/flameshot/blob/master/.github/workflows/deploy-dev-docs.yml + + +[website-build]: https://github.com/flameshot-org/flameshot-org.github.io/blob/master/.github/workflows/build.yml + + +[markdown:reference-style-links]: https://www.markdownguide.org/basic-syntax/#reference-style-links +[mkdocs]: https://www.mkdocs.org/ +[mkdocs-material]: https://squidfunk.github.io/mkdocs-material +[mkdoxy-original]: https://github.com/JakubAndrysek/mkdoxy +[mkdoxy]: https://github.com/veracioux/mkdoxy +[PAT]: https://github.com/settings/tokens?type=beta +[veracioux]: https://github.com/veracioux diff --git a/docs/dev/src/faq.md b/docs/dev/src/faq.md new file mode 100644 index 00000000..07f4c591 --- /dev/null +++ b/docs/dev/src/faq.md @@ -0,0 +1,47 @@ + +# FAQ + +!!! todo + + Incomplete page. + +### How do I create a new subcommand? + +### How do I add a new tool? + +### How do I add a new config setting? + +There are currently two groups of settings: `General` and `Shortcuts`. +The necessary steps are usually the following: + +- Determine a name for the setting - for a general setting, it must be a valid + C++ identifier, for a shortcut it must be the name of a tool type from TODO. +- Add a getter and a setter for the setting in [`ConfigHandler`][ConfigHandler]. + For most settings you should use the + [`CONFIG_GETTER_SETTER`][CONFIG_GETTER_SETTER] macro. If your setting is + unusual enough you may need to use [`CONFIG_GETTER`][CONFIG_GETTER] or + [`CONFIG_SETTER`][CONFIG_SETTER] individually, or even need to create the + methods manually. +- If you need custom validation or conversion for the value, you must create a + subclass of [`ValueHandler`][ValueHandler]. Otherwise you can use one of the + existing ones in [valuehandler.h][]. +- If you want to make your setting available in the configuration GUI (usually + you do), you should add the appropriate widgets into one of the tabs of + [`ConfigWindow`][ConfigWindow]. If your setting doesn't fit into any of the + existing tabs, you can add a new one, but please discuss it with us first. + +To get a deeper understanding of how the configuration works, please see +[Configuration][config]. + +### How do I add a new export action? (@borgmanJeremy @mehrad This is my preferred terminology over final action, need consensus) + +[config]: index.md#configuration +[confighandler.h]: flameshot/confighandler_8h +[confighandler.cpp]: flameshot/confighandler_8cpp +[valuehandler.h]: flameshot/valuehandler_8h +[ValueHandler]: flameshot/classValueHandler +[ConfigHandler]: flameshot/classConfigHandler +[ConfigWindow]: flameshot/classConfigWindow +[CONFIG_GETTER_SETTER]: flameshot/confighandler_8h/#define-config_getter_setter +[CONFIG_GETTER]: flameshot/confighandler_8h/#define-config_getter +[CONFIG_SETTER]: flameshot/confighandler_8h/#define-config_setter diff --git a/docs/dev/src/index.md b/docs/dev/src/index.md new file mode 100644 index 00000000..0a3aa03f --- /dev/null +++ b/docs/dev/src/index.md @@ -0,0 +1,127 @@ +# Flameshot developer docs + +Thank you for your interest in developing flameshot. This developer +documentation (hopefully) has an intuitive structure. It tries to describe what +code is run when a user performs an action in Flameshot. + +!!! important + + **Please read this entire page. It will make your life a whole lot easier when + contributing to Flameshot. If you know exactly what you want to work on, you + should look at [FAQ](./faq) ** + +## Project structure + +Flameshot is built on C++/Qt5 with CMake as its build system. The source code is +located under `src/`. The entrypoint is `src/main.cpp`. + +### `main.cpp` + +Flameshot provides both a GUI and a CLI (the latter currently works only on +Linux and macOS). + +### Build system + +The main cmake file is `CMakeLists.txt` in the project root. It `include`s some +files from the `cmake/` directory as well. These files together control some +more general aspects of the build process, like project information, packaging, +caching etc. + +There is also the file `src/CMakeLists.txt`. It mostly defines how the source +files are compiled into targets and how the external libraries are linked. It +does some other stuff too. Currently, there isn't a clear separation of concerns +between `CMakeLists.txt` and `src/CMakeLists.txt`. In the future we should +refactor these files to make it more clear why each of them exists. + +## What happens when I launch flameshot? +There are two ways to launch flameshot: daemon mode and single-action mode. In +both modes, an instance of [`Flameshot`][Flameshot] is created via +[`Flameshot::start()`][Flameshot::start]. [`Flameshot`][Flameshot] provides the +high level API for interacting with flameshot; and its methods mimic the CLI +subcommands a great deal. This object is a singleton, so it can only be created +once. It is accessed as [`Flameshot::instance()`][Flameshot::instance]. + +!!! note + + On Windows, only daemon mode is currently supported. + +### Single-action mode (via command line interface) +Single-action mode (also called one-off mode) is triggered when flameshot is +launched with a command line argument - for example as `flameshot gui`. As its +name implies, it performs a single action, such as "take a screenshot +interactively by opening a GUI" or "take a screenshot of the entire screen", +etc. Afterwards, Flameshot quits. + +### Daemon mode +This mode is triggered when the `flameshot` command is launched. In this mode, a +flameshot process is started in the background. A system tray is displayed if +the user hasn't disabled it in the config. In addition to [`Flameshot::start()`][Flameshot::start], +if the current process is the daemon, it also calls [`FlameshotDaemon::start()`][FlameshotDaemon::start] +during initialization. + +The daemon has the following purposes: + +- Run in the background, wait for the user to press a hotkey, and perform + corresponding action. + + This is true for **Windows** and **macOS**, but not for **Linux**. On Linux, hotkeys + are meant to be handled by the desktop environment or equivalent. + +- Provide a system tray that the user can click to initiate actions via context + menu + +- Periodically check for updates and notify the user + +- Act as a host for persistent phenomena. Example: On X11 (linux), when a program + inserts content into the clipboard, it must keep running so the content + persists in the clipboard. + +!!! note + + All of the above are user-configurable. + +#### `FlameshotDaemon` +The class [`FlameshotDaemon`][FlameshotDaemon] handles all communication with +the daemon. The class provides public static methods that are designed so that +the caller does not need to know if the current process is a flameshot daemon or +a single-action invocation of Flameshot. If the current process is the daemon, +then the static methods of [`FlameshotDaemon`][FlameshotDaemon] will call the +corresponding instance methods of the singleton. If not, the current process +will communicate with the daemon process via D-Bus. Then, within the daemon +process, those D-Bus calls will be translated into +[`FlameshotDaemon`][FlameshotDaemon] instance method calls. + +## Configuration +The configuration is handled by [`ConfigHandler`][ConfigHandler]. It is +decoupled from any user interface, so it serves the configuration for both the +GUI and CLI. All configuration settings recognized by the config files are +defined as getters in this class. There are also setters for each setting, named +as per the usual convention. For example, the setting `savePath` has a getter +named `savePath` and a setter named `setSavePath`. Before working on a new +config setting for flameshot, please read [this FAQ +entry][faq:add-config-setting]. + +### Interesting notes + +- [`ConfigHandler`][ConfigHandler] is based on `QSettings` +- The configuration uses the `ini` format +- The configuration is automatically reloaded when the config file changes + +## Conventions + +- Always use `&Class::signal` and `&Class::slot` instead of `SIGNAL(signal())` + and `SLOT(slot())`. This usually provides better code introspection and makes + refactoring easier and less error-prone. + +[Flameshot]: flameshot/classFlameshot +[Flameshot::instance]: flameshot/classFlameshot#function-instance +[Flameshot::start]: flameshot/classFlameshot#function-start +[ConfigHandler]: flameshot/classConfigHandler +[FlameshotDaemon]: flameshot/classFlameshotDaemon +[FlameshotDaemon::start]: flameshot/classFlameshotDaemon#function-start +[confighandler.h]: flameshot/confighandler_8h +[confighandler.cpp]: flameshot/confighandler_8cpp + +[faq:add-config-setting]: faq/#how-do-i-add-a-new-config-setting + +[matrix-room]: https://matrix.to/#/#flameshot-org:matrix.org