This will help get new programmers familiar with how to dive in and make
changes quickly, be it adding new features, fixing bugs, or something else.

# Code organization
It's important to note that this repo contains git submodules. In terms of
repos, the important ones are:

- signet-client: this repo, contains the client code for all platforms
- signet-base: firmware that is flashed to the device, and shared code
- crosstool-ng: the cross compiler that is used to build the firmware
- keepassx: code used to import keepass files
- qtcsv: code used to import CSV files

The main directories in this repo are:

- client/: where the client code lives
  - signetapplication.cpp: the main file for the clients
  - desktop/: anything related to the UI will likely live in here
  - esdb/: the code related to storing entries in the database
  - esdb-gui/: code related to showing the GUI to edit entries
- release-notes/: notes about what changed in each version of the app

# Debugging
Debugging is tricky with Signet because it's not always clear whether things
are happening on the device (in firmware), or on the client.

## Debug build
To make a debug build of the client, use this qmake command:

```
qmake client/client.pro CONFIG+=debug
```

To remove compiler optimizations, after running qmake, add `-O0` to the `CFLAGS`
and `CXXFLAGS` lines. If you've already run `make` you'll need to do a
`make clean && make` to rebuild everything with the new settings.

Similarly, adding `-D_FORTIFY_SOURCE=2` to these same lines may be desirable to
get behavior more similar to a release build, but still retain things like
debug prints, symbols, and so forth.

## Client
Using gdb will give you the most control when investigating problems, and this
will be required for debugging complex issues. However, if you want a quick and
dirty approach, you can use the iostream returned by qDebug(). Below is an
example of what that might look like.

```
#include <QDebug>

qDebug() << "[in edit map] Creating generic field " << genericField.name;
qDebug() << QString("example message");
qDebug() << QString("another example").toStdString().c_str();
```

For C files, you'll just have to use printf to stderr. There's nothing special
defined for releases, so you'll just have to look for the absense of
`QT_NO_DEBUG` to limit the printing to when compiled in debug mode.

Example:

```
#ifndef QT_NO_DEBUG
fprintf(stderr, "[signetdev_priv_issue_command] command = %d\n", command);
#endif
```

## Firmware
If the client seems to be sending the correct commands to the device, but the
device is not behaving as expected, it is handy to be able to get some
introspection as to what's happening on the device side. There are UART pins on
the device to help with this.

The TX line is on the pin closer to the edge of the board, with the RX pin
being further towards the center. The UART operates at 115200 baud. You'll
need a USB to Serial breakout board in order to read the messages with a
computer. Setting up the hardware is beyond the scope of this document. Consult
your USB to Serial adapter documentation for additional information.

On the computer that is going to read data from the UART port, the command to
do so is: `screen /dev/ttyUSB0 115200`

When you plug in the device to a computer, it should start printing messages to
the screen session that is running on the computer which is trying to read the
debug messages.

In the firmware, most debug print messages are done with calls to `dprint_s()`,
which is defined in print.h to call `print_s()` which is found in print.c.

# Data structures
The data structures that make up the tree view of passwords (which may be in
groups and subgroups) has been documented in a nice UML diagram here.

![UML diagram](data-model-in-QT.png "UML of data types in tree view")
