Contributor's Guide head task
Open, NormalPublic

Description

This is the head task for creating the contributor's guide as decided on the November 2017 sprint.

Outline

  • What can I do?
  • Spread the word
  • Create learning material
  • Sort out bug reports
  • Fix bugs, develop new features
  • Test and report bugs
  • Translate UI or docs to your language
  • Discuss improvement ideas
  • Maintain binary distributions
  • Anything else you have the skills or resources for? If you're eager to help, there's always something to do

Getting in touch with others

  • IRC
    • Start here. Come and say hi.
    • Don't be afraid to ask questions, but be patient
    • Time of day: we're mostly Europeans
    • Weekly meetings
    • #krita-chat
  • Phabricator
  • Mailing list
  • Bug tracker
    • Triaging bugs
    • Closing bugs
  • Sprints

Testing new versions

Writing documentation

Translating Krita

Building from source

  • Point to a file on the source
  • Compilation arguments (building with tests, asserts, ...)
  • Using an IDE (QtCreator as example)
    • Configuring QtCreator
    • Use spaces instead of tabs
    • Optional: disable compile/deploy before running
    • Opening the project
    • Compiling through QtCreator
    • Running under debugger
    • Useful shortcuts

Programming

  • New to C++ / Qt / KDE? No problem, if you're willing to learn.
  • C++: brief overview, links to useful resources (e.g. no garbage collection, developer is responsible for memory management)
  • Qt: Quick intro, links to Qt documentation
  • KDE frameworks?
  • Krita?
  • Fixing simple bugs or other small issues is a good way to get familiar with the code
  • A brief tour of the source (important, stable concepts)
  • Naming conventions
    • Meanings of prefixes: Q-, K-, Ko-, Kis-, …
  • Organization
    • Top-level folders
    • dockers, tools, paintops, filters, …?
    • Important classes
      • KisApplication, KisMainWindow, KisCanvas
      • KisDocument, KisImage, KisNode, etc.
      • KisPaintDevice
    • (plugins)
    • (strokes)
    • (undo)
  • Libraries used
  • CMakeLists.txt
  • Tips for finding the right file
  • API documentation: https://api.kde.org/extragear-api/graphics-apidocs/krita/html/index.html
  • Search for UI strings
  • Start from a related file, follow symbols
  • Git: blame, log, grep
  • Ask on IRC

Debugging tips(?)

  • Using gdb
  • drmingw
  • llldb

Writing code

HACKING file suggestions

  • Use const whenever applicable
  • Private members (d-pointer): link to KDE docs
  • Use QScopedPointer for private classes
  • Exceptions: don’t throw, but catch from libraries
  • Enum class: don’t use, or refactor to use everywhere
  • auto: as little as possible. Only if the type is obvious
  • nullptr? (TODO: investigate into clang-sanitizer)
  • Don't use Q_ASSERT. Use KIS_ASSERT or KIS_SAFE_ASSERT
  • Prefer QScopedPointer, QScopedArrayPointer, QSharedPointer to manual memory management

Polymorphism

  • Mark overrides
  • Use q_object_cast for QObjects, use static_cast if you’re certain of the class, reinterpret_cast, otherwise dynamic_cast followed by a null check or an assert
  • Never C-style casting

The link http://techbase.kde.org/Policies/Kdelibs_Coding_Style is broken


Content drafts (WIP)
Memory management
Why do we care?
When we create an object using the new operator, a piece of memory is reserved to store the object in. Once the object is no longer needed, the memory should be freed to be used again. If we fail to do this, we will just keep on requesting more and more memory from the system as new object are needed. This is called a memory leak.

Many programming languages have a built-in garbage collector which periodically finds the objects no longer in use and releases those parts of the memory. In C++, however, it is the responsibility us programmers to clean up after ourselves.
How do we do it?
Traditionally, in C++ releasing the memory is done with the delete operator, which is the logical counterpart of new. It releases the object’s memory. The problem with this approach is that it is very easy to forget the delete, especially when the code gets more complicated.

The modern C++ approach is to use so called “smart pointers”. In Krita we use Qt’s implementation of this concept, mainly QScopedPointer and QSharedPointer.
QScopedPointer
A QScopedPointer automatically does the deletion for us when it gets destroyed itself.

The destruction can happen one of two ways. If the scoped pointer was as declared as a local variable, it happens when the program exits the block where the declaration is in. If declared as a field of an object, the scoped pointer is destroyed when the containing object is destroyed.
QSharedPointer
Often we want to refer to the same object from multiple places. If we try to use QScopedPointer, it would delete the object when the first reference is destroyed. This would leave the rest of the references falsely pointing to an area of memory which may now be used for something entirely different. This results in a crash at best, and silent data corruption at worst.

QSharedPointer solves this problem by keeping track of how many shared pointers refer to the object. When the count reaches zero, there should no longer be any reference to the object, so the shared pointer deletes the object.
QWeakSharedPointer?