How to contribute to Drawing
- If you find a bug
- If you want a new feature
- If you want to translate the app
- If you want to fix a bug or to add a new feature:
- How to install from the source code
- If you want to package the app
Usability and design issues concerning existing features are bugs.
- If you can, try to check if it hasn't already been fixed but not released.
- Report it with informations required by the adequate issue template.
- If it's meaningful, try to include screenshots.
Usability and design issues concerning existing features are not new features.
- If you can, try to check if it hasn't already been added but not released.
- Report it with informations required by the adequate issue template.
- In the report, explain what it does, not how it does it.
- Fork the repo and clone your fork on your disk (see installation instructions here)
- If the translation exists but is incomplete:
- Find the file corresponding to you language in the the
po
directory
- Find the file corresponding to you language in the the
- If the translation doesn't exist at all:
- Add your language to
po/LINGUAS
- Build the app once, and then run
ninja -C _build drawing-update-po
at the root of the project. It will produce a.po
file for your language in thepo
directory.
- Add your language to
Use a text editor or an adequate app
to translate the strings of this .po
file. There are comments in the file to
give context helping you to translate some strings, please take them into
account.
Example of something translators can't guess so it's written in the comments: since this app is a clone of MS Paint,
Paint;
(untranslated) has to be in the list of keywords for finding the app in searchable menus or software centers.
- (optional) If you want to test your translation:
- The flatpak SDK isn't able to run a translated version of the app, so export it as a
.flatpak
file and install it withflatpak install path/to/that/file
. - Or (it's harder) install it with
meson
.
- The flatpak SDK isn't able to run a translated version of the app, so export it as a
- Run
git add . && git commit && git push
- Submit a "pull request"/"merge request"
Notice that it will translate the unstable, unreleased version currently
developed on the master
branch, while users may use versions with slightly
different labels you may not have translated. If you want to entirely translate
older versions, restart but run git checkout 0.4
just after the step 1.
- It's better if an issue is reported first
- Easy issues are tagged "good first issue"
- Tell on the issue that you'll try to fix it
If you find some bullshit in the code, or don't understand it, feel free to ask me about it.
To set up a development environment, see here.
- Use tabs in
.py
files. - Use 2 spaces in
.ui
or.xml
files. - Try to not write lines longer than 80 characters.
- In the python code, use double quotes for strings the user might see, and single quotes otherwise (paths, constants, enumerations, dict keys, …)
- Good comments explain why the code does what it does. If a comment explains what it does, the comment is useless, or the code is bad.
I like GAction
s and i've added wrapper methods for using them, try to use that
instead of directly connecting buttons/menu-items to a method.
People sometimes like to design their apps in Glade, while here the main .ui
files are mere templates filled algorithmically according to the user's
settings, you kinda have to run the app to be sure of how your changes to it
actually look like.
Try to respect GNOME Human Interface Guidelines
as much as possible, while making your feature available from the menubar
(in app-menus.ui
). The menubar is hidden in most cases, but it should contains
as many GAction
s as possible for testing purposes (and also because searchable
menus still exist).
If you're contributing to an alternative layout ("elementary OS", "Cinnamon", or any other), please be sure to not hurt the UX with the GNOME layout (since it's the one used on smartphone, be careful it has to stay very resizable).
In my opinion, the difficulties with the code can come mainly from 2 points:
- tools are window-wide, while the operations they produce, which are stored in the history, are image-wide.
- the interactions with the selection are ridiculously complex and numerous (defining, explicit applying, explicit canceling, import, clipboard methods, use by other tools (cancelled or confirmed), deletion, implicit applying, implicit canceling, …) which can easily create small bugs.
The data
directory contains data useless to the execution (app icons, desktop
launcher, settings schemas, appdata, …).
According to some people, it should contain the UI resources, but i don't care:
resources used by the app (.ui
files, in-app icons, …) are in src
, along
with the python code.
main.py
defines the application, which has:
- implementations of CLI handling methods
- some
GioAction
s - a preferences window (
preferences.py
) - a menubar (hidden with most layouts)
- an appmenu (for GNOME Shell ≤ 3.30)
- dialogs (about, shortcuts)
- several windows
window.py
defines a GtkApplicationWindow:
- some
GioAction
s - a "properties" dialog (
properties.py
). It depends on the window despite showing image-wide infos. - a window's decorations can change quite a lot, which is mostly handled by
deco_manager.py
. Three classes are defined in this file:DrDecoManagerMenubar
just hides or shows the menubar. Most of its methods are empty.DrDecoManagerToolbar
loads a toolbar from an UI file. This class extendsDrDecoManagerMenubar
, and will manage a small "hamburger menu" at the end of the toolbar if the menubar is hidden.DrDecoManagerHeaderbar
loads a headerbar from an UI file. This class extendsDrDecoManagerMenubar
but the menubar will always stay hidden. It handles how widgets are shown or hidden depending on the size of the window, and will display various menus depending on the visibility of the buttons, to ensure all features are always available.
- a window has several tools
- a window has several images
minimap.py
for the minimap, which shows a thumbnail of the currently opened image.- each window has an options_manager (
options_manager.py
). It will display the correct bottom bar (= the one required by the current tool) and manage tools' options. All bottom options bars can be found in the sub-directories ofsrc/optionsbars/
, and are specialized fromsrc/optionsbars/abstract_optionsbar.py
image.py
defines an image, which contains:
- an "undo" history and a "redo" history
- a selection, managed by
selection_manager.py
- a
GdkPixbuf.Pixbuf
(as an attribute), namedmain_pixbuf
, which corresponds to the current state of the edited image.
The tools are managed by a bunch of files in the src/tools
directory.
The relationship between the window and the tools is a State design pattern.
The active tool's methods are called from the window's (or the current image's) code regardless of what tool is active. To achieve that, all tools inherit from abstract classes defining common methods.
First of all, src/tools/abstract_tool.py
defines how the tool will be added in
the UI, provides several wrappers to add options, to access the pixbufs, to add
an operation to the edition history, etc. Other common features, when they don't
depend on the image or the tool at all (such as blurring, computing some paths,
displaying an overlay on the image (for the selection for example)), may be
provided by one of the src/tools/utilities_*.py
files.
Then, an other layer of abstract classes is used, depending on the subcategory a tool is in:
- the classic tools, draw on the main pixbuf using
cairo
- the selection tools translates the user's input into operations using the
image's selection_manager. These operations are quite complex, and are
almost entirely managed in
abstract_select.py
. - the "canvas tools" (scale/crop/rotate/filters/…) can be applied to the
selection pixbuf or the main pixbuf, and will use the image's
temp_pixbuf
attribute to store a preview of their changes. These tools have to be explicitely applied by the user.
You will not get updates with this installation method so please do that only for contributing to development, translations, testing, or packaging.
This app is developed using GNOME Builder and its support for flatpak
:
- Open GNOME Builder
- Click on "Clone a repository…" and use this address:
https://github.com/maoschanz/drawing.git
- Open it as a project with GNOME Builder
- Be sure the runtime is installed (if it doesn't suggest it automatically, Ctrl+Return → type
update-dependencies
) - Click on the Run button
See here for the list of dependencies.
Get the code:
git clone https://github.com/maoschanz/drawing.git
Build the app:
cd drawing
meson _build
ninja -C _build
Install the app (system-wide):
sudo ninja -C _build install
(if you know the options to install user-wide, please tell)
The app can then be removed with:
cd _build
sudo ninja uninstall
With flatpak-builder (not recommended, that's just for me)
Initial setup of the local flatpak repository:
wget https://raw.githubusercontent.com/maoschanz/drawing/master/com.github.maoschanz.drawing.json
flatpak-builder --force-clean _build2/ --repo=_repo com.github.maoschanz.drawing.json
flatpak --user remote-add --no-gpg-verify local-drawing-repo _repo
flatpak --user install local-drawing-repo com.github.maoschanz.drawing
Update:
flatpak-builder --force-clean _build2/ --repo=_repo com.github.maoschanz.drawing.json
flatpak update
You can also build a debian package with the script deb_package.sh
, but you
won't get updates that way, so don't do that. You probably don't have all the
dependencies to make it work anyway.
The master
branch is not stable and should not be packaged.
Stable versions for end-users are tagged, and listed on this Github repo's
"Releases" tab. For now, most of them are on the 0.4
branch.
Dependencies to run the app:
- GObject Introspection (GI) for python3 (on Debian, it's
python3-gi
). A version ≥3.30.0 is required to run the code from the branchmaster
. The branch0.4
should be fine with any version. cairo
library's GI for python3 (on Debian, it'spython3-gi-cairo
).- GTK libraries' GI (on Debian, it's
gir1.2-gtk-3.0
).
Dependencies to build the app (Debian packages names):
meson
. The version required by themeson.build
file at the root of the project can be changed if necessary, but please don't add this change to your commit(s).appstream-util
(validation of the.appdata.xml
file)libglib2.0-dev-bin
(IIRC that one is to compress the.ui
files and the icons into a.gresource
file)