22 #include <QtGui/QPainter>
23 #include <QtCore/QMutableVectorIterator>
25 class KWordWrapPrivate {
27 QRect m_constrainingRect;
28 QVector<int> m_breakPositions;
29 QVector<int> m_lineWidths;
34 KWordWrap::KWordWrap(
const QRect & r)
35 : d(new KWordWrapPrivate)
37 d->m_constrainingRect = r;
47 int height = fm.height();
51 kw->d->m_text = str.left( len );
60 bool isBreakable =
false;
61 bool wasBreakable =
false;
62 bool isParens =
false;
63 bool wasParens =
false;
66 for (
int i = 0 ; i < len; ++i )
68 const QChar c = inputString.at(i);
69 const int ww = fm.charWidth(inputString, i);
71 isParens = ( c == QLatin1Char(
'(') || c == QLatin1Char(
'[')
72 || c == QLatin1Char(
'{') );
74 isBreakable = ( c.isSpace() || c.isPunct() || c.isSymbol() ) & !isParens;
77 if ( !isBreakable && i < len-1 ) {
78 const QChar nextc = inputString.at(i + 1);
79 isBreakable = ( nextc == QLatin1Char(
'(')
80 || nextc == QLatin1Char(
'[')
81 || nextc == QLatin1Char(
'{') );
86 if ( c == QLatin1Char(
'/') && (wasBreakable || wasParens) )
93 if ( x + ww > w && lastBreak != -1 )
95 if ( x + ww > w - 4 && lastBreak == -1 )
97 if (i == len - 2 && x + ww + fm.charWidth(inputString, i+1) > w)
98 breakAt = lastBreak == -1 ? i - 1 : lastBreak;
99 if ( c == QLatin1Char(
'\n') )
101 if ( breakAt == -1 && lastBreak != -1)
107 kw->d->m_text.remove(i, 1);
108 inputString.remove(i, 1);
114 kw->d->m_breakPositions.append( breakAt );
115 int thisLineWidth = lastBreak == -1 ? x + ww : lineWidth;
116 kw->d->m_lineWidths.append( thisLineWidth );
117 textwidth = qMax( textwidth, thisLineWidth );
122 if ( lastBreak != -1 )
129 }
else if ( isBreakable )
135 wasBreakable = isBreakable;
136 wasParens = isParens;
138 textwidth = qMax( textwidth, x );
139 kw->d->m_lineWidths.append( x );
142 if ( r.height() >= 0 && y > r.height() )
143 textwidth = r.width();
145 if ( r.height() >= 0 )
147 while ( realY > r.height() )
149 realY = qMax( realY, 0 );
151 kw->d->m_boundingRect.setRect( 0, 0, textwidth, realY );
164 for (
int i = 0; i < d->m_breakPositions.count(); ++i) {
165 int end = d->m_breakPositions.at(i);
166 ws += d->m_text.mid( start, end - start + 1 );
167 ws += QLatin1Char(
'\n');
170 ws += d->m_text.mid( start );
176 if ( d->m_breakPositions.isEmpty() )
179 QString ts = d->m_text.left( d->m_breakPositions.first() + 1 );
181 ts += QLatin1String(
"...");
186 return QColor(
int(c1.red() * p1 + c2.red() * (1.0-p1)),
187 int(c1.green() * p1 + c2.green() * (1.0-p1)),
188 int(c1.blue() * p1 + c2.blue() * (1.0-p1)));
193 QFontMetrics fm = p->fontMetrics();
194 QColor bgColor = p->background().color();
195 QColor textColor = p->pen().color();
197 if ( ( fm.boundingRect( t ).width() > maxW ) && ( t.length() > 1 ) ) {
200 while ( tl < t.length() ) {
201 w += fm.charWidth( t, tl );
207 int n = qMin( tl, 3);
208 if ( t.isRightToLeft() ) {
211 x -= fm.width( t.left( tl - 3 ) );
212 p->drawText( x, y, t.left( tl - 3 ) );
214 for (
int i = 0; i < n; i++) {
215 p->setPen(
mixColors( 0.70 - i * 0.25, textColor, bgColor ) );
216 QString s( t.at( tl - n + i ) );
218 p->drawText( x, y, s );
223 p->drawText( x, y, t.left( tl - 3 ) );
224 x += fm.width( t.left( tl - 3 ) );
226 for (
int i = 0; i < n; i++) {
227 p->setPen(
mixColors( 0.70 - i * 0.25, textColor, bgColor ) );
228 QString s( t.at( tl - n + i ) );
229 p->drawText( x, y, s );
235 p->drawText( x, y, t );
240 QString tmpText = p->fontMetrics().elidedText(t, Qt::ElideRight, maxW);
241 p->drawText( x, y, tmpText );
250 QFontMetrics fm = painter->fontMetrics();
251 int height = fm.height();
252 int ascent = fm.ascent();
253 int maxwidth = d->m_boundingRect.width();
257 for (i = 0; i < d->m_breakPositions.count() ; ++i )
260 if ( (d->m_constrainingRect.height() >= 0) &&
261 ((y + 2 * height) > d->m_constrainingRect.height()) )
263 end = d->m_breakPositions.at(i);
264 lwidth = d->m_lineWidths.at(i);
266 if ( flags & Qt::AlignHCenter )
267 x += ( maxwidth - lwidth ) / 2;
268 else if ( flags & Qt::AlignRight )
269 x += maxwidth - lwidth;
270 painter->drawText( x, textY + y + ascent, d->m_text.mid( start, end - start + 1 ) );
276 lwidth = d->m_lineWidths.last();
278 if ( flags & Qt::AlignHCenter )
279 x += ( maxwidth - lwidth ) / 2;
280 else if ( flags & Qt::AlignRight )
281 x += maxwidth - lwidth;
282 if ( (d->m_constrainingRect.height() < 0) ||
283 ((y + height) <= d->m_constrainingRect.height()) ) {
284 if ( i == d->m_breakPositions.count() )
285 painter->drawText( x, textY + y + ascent, d->m_text.mid( start ) );
288 d->m_constrainingRect.width(),
289 d->m_text.mid( start ) );
292 d->m_constrainingRect.width(),
293 d->m_text.mid( start ) );
295 painter->drawText( x, textY + y + ascent,
296 d->m_text.mid( start ) );
302 return d->m_boundingRect;
static void drawTruncateText(QPainter *p, int x, int y, int maxW, const QString &t)
Draws the string t at the given coordinates, if it does not fit into maxW the text will be truncated...
QString truncatedString(bool dots=true) const
static void drawFadeoutText(QPainter *p, int x, int y, int maxW, const QString &t)
Draws the string t at the given coordinates, if it does not fit into maxW the text will be faded out...
static QColor mixColors(double p1, QColor c1, QColor c2)
QRect boundingRect() const
Word-wrap algorithm that takes into account beautifulness ;)
QString wrappedString() const
void drawText(QPainter *painter, int x, int y, int flags=Qt::AlignLeft) const
Draw the text that has been previously wrapped, at position x,y.
static KWordWrap * formatText(QFontMetrics &fm, const QRect &r, int flags, const QString &str, int len=-1)
Main method for wrapping text.
const KShortcut & end()
Goto end of the document.