1 /***************************************************************************
2 * Copyright (C) 2005-09 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 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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);
44 void StyledLabel::setCustomFont(const QFont &font) {
46 _layout.setFont(font);
47 setText(_layout.text());
50 void StyledLabel::setWrapMode(QTextOption::WrapMode mode) {
55 QTextOption opt = _layout.textOption();
56 opt.setWrapMode(mode);
57 _layout.setTextOption(opt);
62 void StyledLabel::setAlignment(Qt::Alignment alignment) {
63 if(_alignment == alignment)
66 _alignment = alignment;
67 QTextOption opt = _layout.textOption();
68 opt.setAlignment(alignment);
69 _layout.setTextOption(opt);
74 void StyledLabel::setResizeMode(ResizeMode mode) {
75 if(_resizeMode == mode)
79 if(mode == DynamicResize)
80 setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
82 setWrapMode(QTextOption::NoWrap);
85 void StyledLabel::resizeEvent(QResizeEvent *event) {
86 QFrame::resizeEvent(event);
91 QSize StyledLabel::sizeHint() const {
95 void StyledLabel::updateSizeHint() {
97 int padding = frameWidth() * 2;
98 sh = _layout.boundingRect().size().toSize() + QSize(padding, padding);
100 if(_sizeHint != sh) {
106 void StyledLabel::setText(const QString &text) {
107 UiStyle *style = GraphicalUi::uiStyle();
109 UiStyle::StyledString sstr = style->styleString(style->mircToInternal(text), UiStyle::PlainMsg);
110 QList<QTextLayout::FormatRange> layoutList = style->toTextLayoutList(sstr.formatList, sstr.plainText.length(), 0);
112 // Use default font rather than the style's
113 QTextLayout::FormatRange fmtRange;
114 fmtRange.format.setFont(font());
116 fmtRange.length = sstr.plainText.length();
117 layoutList << fmtRange;
120 _clickables = ClickableList::fromString(sstr.plainText);
121 foreach(Clickable click, _clickables) {
122 if(click.type() == Clickable::Url) {
123 QTextLayout::FormatRange range;
124 range.start = click.start();
125 range.length = click.length();
126 range.format.setForeground(palette().link());
131 _layout.setText(sstr.plainText);
132 _layout.setAdditionalFormats(layoutList);
139 void StyledLabel::updateToolTip() {
140 if(frameRect().width() - 2*frameWidth() < _layout.minimumWidth())
141 setToolTip(QString("<qt>%1</qt>").arg(Qt::escape(_layout.text()))); // only rich text gets wordwrapped!
143 setToolTip(QString());
146 void StyledLabel::layout() {
148 qreal w = contentsRect().width();
150 _layout.beginLayout();
152 QTextLine line = _layout.createLine();
155 line.setLineWidth(w);
156 line.setPosition(QPointF(0, h));
166 void StyledLabel::paintEvent(QPaintEvent *e) {
167 QFrame::paintEvent(e);
168 QPainter painter(this);
170 qreal y = contentsRect().y() + (contentsRect().height() - _layout.boundingRect().height()) / 2;
171 _layout.draw(&painter, QPointF(contentsRect().x(), y), _extraLayoutList);
174 int StyledLabel::posToCursor(const QPointF &pos) {
175 if(pos.y() < 0 || pos.y() > height())
178 for(int l = _layout.lineCount() - 1; l >= 0; l--) {
179 QTextLine line = _layout.lineAt(l);
180 if(pos.y() >= line.y()) {
181 return line.xToCursor(pos.x(), QTextLine::CursorOnCharacter);
187 void StyledLabel::mouseMoveEvent(QMouseEvent *event) {
188 if(event->buttons() == Qt::NoButton) {
189 Clickable click = _clickables.atCursorPos(posToCursor(event->posF()));
191 setHoverMode(click.start(), click.length());
197 void StyledLabel::enterEvent(QEvent *) {
198 if(resizeMode() == ResizeOnHover)
199 setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
202 void StyledLabel::leaveEvent(QEvent *) {
204 if(resizeMode() == ResizeOnHover)
205 setWrapMode(QTextOption::NoWrap);
208 void StyledLabel::mousePressEvent(QMouseEvent *event) {
209 if(event->button() == Qt::LeftButton) {
210 Clickable click = _clickables.atCursorPos(posToCursor(event->posF()));
212 emit clickableActivated(click);
216 void StyledLabel::setHoverMode(int start, int length) {
217 if(_extraLayoutList.count() >= 1 && _extraLayoutList.first().start == start && _extraLayoutList.first().length == length)
220 QTextLayout::FormatRange range;
222 range.length = length;
223 range.format.setFontUnderline(true);
224 _extraLayoutList.clear();
225 _extraLayoutList << range;
227 setCursor(Qt::PointingHandCursor);
231 void StyledLabel::endHoverMode() {
232 _extraLayoutList.clear();
233 setCursor(Qt::ArrowCursor);