Skip to content

Commit

Permalink
[v0.10.0] #151, Add line based QTextLayout format additions (#153)
Browse files Browse the repository at this point in the history
Via edbee::LineData (LineAppendTextLayoutFormatListField). see: `edbee-lib/doc/line_data.md` for sample
  • Loading branch information
gamecreature authored Feb 27, 2025
1 parent 09bfbc0 commit ca05904
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 49 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Changelog

- (2025-02-27) [v0.10.0] #151, Add line based QTextLayout format additions
Via edbee::LineData (LineAppendTextLayoutFormatListField). see: `edbee-lib/doc/line_data.md` for sample

- (2025-01-24) [v0.9.0] #150, Add version number (EDBEE_VERSION / Edbee::instance()->version())
- (2025-01-24) #145, Replace onigmo with onigruma
Expand Down
75 changes: 35 additions & 40 deletions edbee-lib/doc/coding-style.md
Original file line number Diff line number Diff line change
@@ -1,89 +1,85 @@
Coding Style {#coding-style}
============
# Coding Style {#coding-style}

The coding style is based on google's styleguide:
The coding style is based on google's styleguide:

<http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml>

* default names: defaultNames
* class names : ClassNames
* const names : CONSTANT_NAMES
* const names : `CONSTANT_NAMES`

Reference, pointer location can be placed next to type typename or to the variable name
* good: TypeName* object; TypeName& name;
* good: TypeName *object; TypeName &name;
* bad: TypeName * object; TypeName & name;
* good: `TypeName* object; TypeName& name;`
* good: `TypeName *object; TypeName &name;`
* bad: `TypeName * object; TypeName & name;`


Member instances should be private. Subclasses should never access data members directly unless it's stricly necessary.

class members
-------------
## class members

A class member name is postfixed with '_'. (To prevent clashes with getter functions)

~~~{.cpp}
```cpp
int itemName_;
~~~
```

A class member pointer that is NOT owned by the classes show be postfixed with "Ref".
A class member pointer that is NOT owned by the classes show be postfixed with "Ref".
For example a reference to a buffer is added like this

~~~{.cpp}
```cpp
TextBuffer* bufferRef_;
~~~
```

When you have a list of reference the following name is used:

~~~{.cpp}
```cpp
QList<Item*> itemRefList_;
~~~
int x = 12;
```


Method definitions
------------------
## Method definitions

Separate methods from each other with 2 blank lines. This improves the visible separation of method bodies.


Ownership
---------
## Ownership

In C / C++ you need to do your own garabage collection. So ownership is important. Here are some rules to make the
ownership in the code clear:

* all class members are 'owned' by the class. If not add the postfix "Ref" (see class members)
* transfering ownership from x => y, prefix the function with the word "give" or "take".
* transfering ownership from x => y, prefix the function with the word "give" or "take".
* object.give( x ) gives the ownership of x to object
* object.take( x ) removes the ownership of x from object

When it is possible for a class to have the ownership of an object optionally, the way to do this is the following. (See redbee::TextEditorController.textDocument[Ref])

* give the class 2 members. For example in the case of a document:
* document_, this is the 'owned' document (only if the document is owner else it is 0)
* documentRef_ , this is the reference to the document. This can be a reference to document_
* documentRef_ , this is the reference to the document. This can be a reference to document_
* For working with the document the documentRef_ member is used
* For destruction/giving etc. the document_ member is used

When using lists yout can use the following structure
When using lists yout can use the following structure

~~~{.cpp}
QList<ClassName*> objectList_ ; // when owning the items (use qDeleteAll in the destructor)
```cpp
QList<ClassName*> objectList_ ; // when owning the items (use qDeleteAll in the destructor)
QList<ClassName*> objectRefList_; // use this when you do not own the objectlist
~~~
```


Memory Leak Detection and include order
---------------------------------------
## Memory Leak Detection and include order

We use custom memory leak detection. To enable this leak detection it is required to include 'debug.h'
You must include "debug.h" in every Source file AFTER all pre-compiled items and header files. Example:

~~~{.cpp}
~~~{.cpp}
// first you should include the source's header file. (This allows you to see if the headers users 'missing' dependencies'
#include "header-file-of-this-source-file.h"
// then include all Qt headers (and other external libraries) (sorted alpabeticly).
// then include all Qt headers (and other external libraries) (sorted alpabeticly).
#include <QHeaders>
// after this include your other header files from your project (alpabeticly is nice!)
Expand All @@ -97,8 +93,7 @@ This implies that you should never use a new or delete keyword in a header file!
main.cpp is different, it includes all DEBUG_NEW stuff below ALL existing header files!


Documentation
--------------
## Documentation

We make use of doxygen: <http://www.doxygen.org>

Expand All @@ -107,18 +102,18 @@ We make use of doxygen: <http://www.doxygen.org>
- Put method documentation in the source file of the class


Header files
------------
- Use #pragma once.. Most platforms support this keyword, so use it. #ifdef structure is outdated
## Header files

- Use `#pragma once`.. Most platforms support this keyword, so use it. `#ifdef` structure is outdated
- Never use code in a header file. Even not for getters and setters. (It has been done in this project on certain places, but recommendation is to not do it, because it can case strange build errors)
- You can make an exception (of course) for template classes / function
- limit the use of templates! This slows down the compilation process and gives very crappy error messages
- Prefer pointers/references above class inclusions in the header file
- limit the use of templates! This slows down the compilation process and gives very crappy error messages
- Prefer pointers/references above class inclusions in the header file


## Enumerations

Enumerations
------------
On several places in the code you will find enumeration definitions. We do not aways force the enumeration
On several places in the code you will find enumeration definitions. We do not aways force the enumeration
type for variables. The reason for this is, that somethimes it's desirable to extends the number of enumeration options.
And when forcing a enumeration type, you cannot easy pass a custom value and are limited to the predefined definitions.

Expand Down
10 changes: 7 additions & 3 deletions edbee-lib/doc/index.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
edbee documentation {#mainpage}
===================
# edbee documentation {#mainpage}

This is the generated documentation for the edbee library.
Please use the menu above to navigate...

[Coding Style](@ref coding-style)
[Coding Style](coding-style.md)

### Features

[Line Data](line_data.md)

... a big todo to show explain samples/features ...
58 changes: 58 additions & 0 deletions edbee-lib/doc/line_data.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Line data

Linedata support add the support for adding custom data to TextDocument lines.
These data items are automaticly moved/delete when inserting/deleting lines.

The line data is a fixed with array with pointers and is reserved for every line.
The enum `TextLineDataPredefinedFields` defines the predefined fields that are built in edbee.
The `PredefinedFieldCount' value can be used to find out where to start defining your custom types.

To use extra custom fields you are required to set the number of fields to reserve.
This can be done with `editor->textDocument()->lineDataManager()->setFieldsPerLine(3)`
which needs to have at least the length of PredefinedFieldCount.


## General usage

To set a file for a given line you can invoke the giveLineData method.

```cpp
textDocument()->giveLineData(line, edbee::LineAppendTextLayoutFormatListField, data);
```
Removing can be done by supplying a nullptr to the data
```cpp
textDocument()->giveLineData(line, edbee::LineAppendTextLayoutFormatListField, nullptr);
```

## Predefined variable `LineAppendTextLayoutFormatListField`

The predefined `LineAppendTextLayoutFormatListField` field type can be used to
add custom `<QTextLayout::Format>` ranges to the QTextLayout of a line.

For example, to add a waved red underline:

```cpp
// Set the line data for a given line (assuming this line is in the document!!)
int line = 2;

// build a list of QTextLayout::FormatRanges
QList<QTextLayout::FormatRange> formatRanges;

QTextLayout::FormatRange formatRange;
formatRange.start = 0;
formatRange.length = editor->textDocument()->lineLength(line);
formatRange.format.setUnderlineStyle(QTextCharFormat::WaveUnderline);
formatRange.format.setUnderlineColor(Qt::red);
formatRanges.append(formatRange);

// build a line data item (which is added to the TextLineData)
edbee::LineAppendTextLayoutFormatListData *formatRangesListData = new edbee::LineAppendTextLayoutFormatListData(formatRanges);
editor->textDocument()->giveLineData(line, edbee::LineAppendTextLayoutFormatListField, formatRangesListData);
```
Because every line has it's own QTextLayout the range offset of the given line is 0.
4 changes: 2 additions & 2 deletions edbee-lib/edbee/edbeeversion.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#pragma once

#define EDBEE_VERSION "0.9.0"
#define EDBEE_VERSION "0.10.0"

#define EDBEE_VERSION_MAJOR 0
#define EDBEE_VERSION_MINOR 9
#define EDBEE_VERSION_MINOR 10
#define EDBEE_VERSION_PATCH 0
#define EDBEE_VERSION_POSTFIX ""
9 changes: 6 additions & 3 deletions edbee-lib/edbee/models/textlinedata.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "edbee/exports.h"

#include <QObject>
#include <QTextLayout>

#include "edbee/util/gapvector.h"

Expand All @@ -16,8 +17,9 @@ namespace edbee {

enum TextLineDataPredefinedFields {
LineTextScopesField=0,
// LineDataMarkers, /// Bookmarks etc
PredefinedFieldCount=1
// LineDataMarkers, /// Bookmarks etc
LineAppendTextLayoutFormatListField=1,
PredefinedFieldCount=2
};


Expand Down Expand Up @@ -47,8 +49,9 @@ class EDBEE_EXPORT BasicTextLineData : public TextLineData
T value_;
};

typedef BasicTextLineData<QString> QStringTextLineData;

typedef BasicTextLineData<QString> QStringTextLineData;
typedef BasicTextLineData<QList<QTextLayout::FormatRange>> LineAppendTextLayoutFormatListData;

//-------

Expand Down
10 changes: 9 additions & 1 deletion edbee-lib/edbee/views/textrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <QStringList>
#include <QTextLayout>

#include "edbee/models/textlinedata.h"
#include "edbee/util/simpleprofiler.h"

#include "edbee/models/chardocument/chartextdocument.h"
Expand Down Expand Up @@ -319,8 +320,8 @@ TextLayout *TextRenderer::textLayoutForLineForPlaceholder(int line)
formatRange.length = text.length();
formatRange.format = format;
formatRanges.append(formatRange);
textLayout->setFormats(formatRanges);

textLayout->setFormats(formatRanges);
textLayout->setText(text);
textLayout->buildLayout();

Expand Down Expand Up @@ -400,6 +401,13 @@ TextLayout *TextRenderer::textLayoutForLineNormal(int line)
}
}
}

// append some extra formatting (if available)
edbee::LineAppendTextLayoutFormatListData* formatRangeLineData = dynamic_cast<edbee::LineAppendTextLayoutFormatListData*>(textDocument()->getLineData(line, edbee::LineAppendTextLayoutFormatListField));
if (formatRangeLineData) {
formatRanges.append(formatRangeLineData->value());
}

textLayout->setFormats(formatRanges);

#ifdef USE_CONTROL_PICTURES
Expand Down

0 comments on commit ca05904

Please sign in to comment.