1 /***************************************************************************
2 * Copyright (C) 2005-2014 by the Quassel Project *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
22 #include <QTextDocument>
23 #include <QTextLayout>
25 #include "graphicalui.h"
26 #include "styledlabel.h"
29 StyledLabel::StyledLabel(QWidget *parent)
31 _wrapMode(QTextOption::NoWrap),
32 _alignment(Qt::AlignVCenter|Qt::AlignLeft),
33 _toolTipEnabled(true),
36 setMouseTracking(true);
38 QTextOption opt = _layout.textOption();
39 opt.setWrapMode(_wrapMode);
40 opt.setAlignment(_alignment);
41 _layout.setTextOption(opt);
45 void StyledLabel::setCustomFont(const QFont &font)
48 _layout.setFont(font);
49 setText(_layout.text());
53 void StyledLabel::setWrapMode(QTextOption::WrapMode mode)
55 if (_wrapMode == mode)
59 QTextOption opt = _layout.textOption();
60 opt.setWrapMode(mode);
61 _layout.setTextOption(opt);
67 void StyledLabel::setAlignment(Qt::Alignment alignment)
69 if (_alignment == alignment)
72 _alignment = alignment;
73 QTextOption opt = _layout.textOption();
74 opt.setAlignment(alignment);
75 _layout.setTextOption(opt);
81 void StyledLabel::setResizeMode(ResizeMode mode)
83 if (_resizeMode == mode)
87 if (mode == DynamicResize)
88 setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
90 setWrapMode(QTextOption::NoWrap);
94 void StyledLabel::resizeEvent(QResizeEvent *event)
96 QFrame::resizeEvent(event);
102 QSize StyledLabel::sizeHint() const
108 void StyledLabel::updateSizeHint()
111 int padding = frameWidth() * 2;
112 sh = _layout.boundingRect().size().toSize() + QSize(padding, padding);
114 if (_sizeHint != sh) {
121 void StyledLabel::setText(const QString &text)
123 UiStyle *style = GraphicalUi::uiStyle();
125 UiStyle::StyledString sstr = style->styleString(style->mircToInternal(text), UiStyle::PlainMsg);
126 QList<QTextLayout::FormatRange> layoutList = style->toTextLayoutList(sstr.formatList, sstr.plainText.length(), 0);
128 // Use default font rather than the style's
129 QTextLayout::FormatRange fmtRange;
130 fmtRange.format.setFont(font());
132 fmtRange.length = sstr.plainText.length();
133 layoutList << fmtRange;
136 _clickables = ClickableList::fromString(sstr.plainText);
137 foreach(Clickable click, _clickables) {
138 if (click.type() == Clickable::Url) {
139 QTextLayout::FormatRange range;
140 range.start = click.start();
141 range.length = click.length();
142 range.format.setForeground(palette().link());
147 _layout.setText(sstr.plainText);
148 _layout.setAdditionalFormats(layoutList);
156 void StyledLabel::updateToolTip()
158 if (frameRect().width() - 2*frameWidth() < _layout.minimumWidth())
159 setToolTip(QString("<qt>%1</qt>").arg(Qt::escape(_layout.text()))); // only rich text gets wordwrapped!
161 setToolTip(QString());
165 void StyledLabel::layout()
168 qreal w = contentsRect().width();
170 _layout.beginLayout();
172 QTextLine line = _layout.createLine();
175 line.setLineWidth(w);
176 line.setPosition(QPointF(0, h));
187 void StyledLabel::paintEvent(QPaintEvent *e)
189 QFrame::paintEvent(e);
190 QPainter painter(this);
192 qreal y = contentsRect().y() + (contentsRect().height() - _layout.boundingRect().height()) / 2;
193 _layout.draw(&painter, QPointF(contentsRect().x(), y), _extraLayoutList);
197 int StyledLabel::posToCursor(const QPointF &pos)
199 if (pos.y() < 0 || pos.y() > height())
202 for (int l = _layout.lineCount() - 1; l >= 0; l--) {
203 QTextLine line = _layout.lineAt(l);
204 if (pos.y() >= line.y()) {
205 return line.xToCursor(pos.x(), QTextLine::CursorOnCharacter);
212 void StyledLabel::mouseMoveEvent(QMouseEvent *event)
214 if (event->buttons() == Qt::NoButton) {
215 Clickable click = _clickables.atCursorPos(posToCursor(event->posF()));
217 setHoverMode(click.start(), click.length());
224 void StyledLabel::enterEvent(QEvent *)
226 if (resizeMode() == ResizeOnHover)
227 setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
231 void StyledLabel::leaveEvent(QEvent *)
234 if (resizeMode() == ResizeOnHover)
235 setWrapMode(QTextOption::NoWrap);
239 void StyledLabel::mousePressEvent(QMouseEvent *event)
241 if (event->button() == Qt::LeftButton) {
242 Clickable click = _clickables.atCursorPos(posToCursor(event->posF()));
244 emit clickableActivated(click);
249 void StyledLabel::setHoverMode(int start, int length)
251 if (_extraLayoutList.count() >= 1 && _extraLayoutList.first().start == start && _extraLayoutList.first().length == length)
254 QTextLayout::FormatRange range;
256 range.length = length;
257 range.format.setFontUnderline(true);
258 _extraLayoutList.clear();
259 _extraLayoutList << range;
261 setCursor(Qt::PointingHandCursor);
266 void StyledLabel::endHoverMode()
268 _extraLayoutList.clear();
269 setCursor(Qt::ArrowCursor);