Custom text wrapping - find position where text line gets too long
-
I display some strings which might need to be treated with a custom text wrapping rule, because there are certain characters where wrapping should occur.
For example:
An.Address.Which.Separates.With.Dots
should break where the dots are, before the line gets too long:
An.Address.
Which.Separates.
With.Dots
For this, I have a simple algorithm: Split the string into a list of fragment strings at exactly those characters, and start re-assembling the whole string, inserting line breaks at the predefined positions whenever a line gets too long.
The catch: In case a string fragment is longer than a line should be, I need to break elsewhere. My preferred location would be just before the position where the line gets too long. But how can I get the right position?
I would like to avoid the brute-force approach:- Test string length (using QFontMetrics)
- Add one character
- Repeat
Things I have:
- Source string
- Font to use
Things I don't have
- Any widgets or GUI elements
-
Because of how letters can interact in different fonts I don't think you can avoid QFontMetrics::width.
Instead of doing it one character at a time I would try something like this:- use some approx way to determine minimum characters that would fit (the more precise it is the better, but anything will do, e.g. constant width for a character)
- use the same to approx maximum number of characters that would fit
- do a binary search between the two values and test each with QFontMetrics::width.
If you do a good approx on the first two it should be just a couple of checks for any length of a string.
-
I was half hoping such an implementation already exists within Qt. Otherwise, it's a reasonable approach. Thanks.
-
One semi-nice way comes to mind. You could use QFontMetrics::elidedText to get the part that fits in a line. The downside is that you would get the text with "...", but you can measure the width of "..." first, add that width to the maximum line width for measurement and then remove the dots from resulting string.