1 /***************************************************************************
2 * Copyright (C) 2005-2019 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 ***************************************************************************/
21 #include "styledlabel.h"
24 #include <QTextDocument>
25 #include <QTextLayout>
27 #include "graphicalui.h"
30 StyledLabel::StyledLabel(QWidget* parent)
32 , _alignment(Qt::AlignVCenter | Qt::AlignLeft)
34 setMouseTracking(true);
36 QTextOption opt = _layout.textOption();
37 opt.setWrapMode(_wrapMode);
38 opt.setAlignment(_alignment);
39 _layout.setTextOption(opt);
42 void StyledLabel::setCustomFont(const QFont& font)
45 _layout.setFont(font);
46 setText(_layout.text());
49 void StyledLabel::setWrapMode(QTextOption::WrapMode mode)
51 if (_wrapMode == mode)
55 QTextOption opt = _layout.textOption();
56 opt.setWrapMode(mode);
57 _layout.setTextOption(opt);
62 void StyledLabel::setAlignment(Qt::Alignment alignment)
64 if (_alignment == alignment)
67 _alignment = alignment;
68 QTextOption opt = _layout.textOption();
69 opt.setAlignment(alignment);
70 _layout.setTextOption(opt);
75 void StyledLabel::setResizeMode(ResizeMode mode)
77 if (_resizeMode == mode)
81 if (mode == DynamicResize)
82 setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
84 setWrapMode(QTextOption::NoWrap);
87 void StyledLabel::resizeEvent(QResizeEvent* event)
89 QFrame::resizeEvent(event);
94 QSize StyledLabel::sizeHint() const
99 void StyledLabel::updateSizeHint()
102 int padding = frameWidth() * 2;
103 sh = _layout.boundingRect().size().toSize() + QSize(padding, padding);
105 if (_sizeHint != sh) {
111 void StyledLabel::setText(const QString& text)
113 UiStyle* style = GraphicalUi::uiStyle();
115 UiStyle::StyledString sstr = style->styleString(style->mircToInternal(text), UiStyle::FormatType::PlainMsg);
116 QList<QTextLayout::FormatRange> layoutList = style->toTextLayoutList(sstr.formatList, sstr.plainText.length(), UiStyle::MessageLabel::None);
118 // Use default font rather than the style's
119 QTextLayout::FormatRange fmtRange;
120 fmtRange.format.setFont(font());
122 fmtRange.length = sstr.plainText.length();
123 layoutList << fmtRange;
126 _clickables = ClickableList::fromString(sstr.plainText);
127 foreach (Clickable click, _clickables) {
128 if (click.type() == Clickable::Url) {
129 QTextLayout::FormatRange range;
130 range.start = click.start();
131 range.length = click.length();
132 range.format.setForeground(palette().link());
137 _layout.setText(sstr.plainText);
138 _layout.setAdditionalFormats(layoutList);
145 void StyledLabel::updateToolTip()
147 if (frameRect().width() - 2 * frameWidth() < _layout.minimumWidth())
148 setToolTip(QString("<qt>%1</qt>").arg(_layout.text().toHtmlEscaped())); // only rich text gets wordwrapped!
150 setToolTip(QString());
153 void StyledLabel::layout()
156 qreal w = contentsRect().width();
158 _layout.beginLayout();
161 QTextLine line = _layout.createLine();
164 line.setLineWidth(w);
165 line.setPosition(QPointF(0, h));
175 void StyledLabel::paintEvent(QPaintEvent* e)
177 QFrame::paintEvent(e);
178 QPainter painter(this);
180 qreal y = contentsRect().y() + (contentsRect().height() - _layout.boundingRect().height()) / 2;
181 _layout.draw(&painter, QPointF(contentsRect().x(), y), _extraLayoutList);
184 int StyledLabel::posToCursor(const QPointF& pos)
186 if (pos.y() < 0 || pos.y() > height())
189 for (int l = _layout.lineCount() - 1; l >= 0; l--) {
190 QTextLine line = _layout.lineAt(l);
191 if (pos.y() >= line.y()) {
192 return line.xToCursor(pos.x(), QTextLine::CursorOnCharacter);
198 void StyledLabel::mouseMoveEvent(QMouseEvent* event)
200 if (event->buttons() == Qt::NoButton) {
201 Clickable click = _clickables.atCursorPos(posToCursor(event->localPos()));
203 setHoverMode(click.start(), click.length());
209 void StyledLabel::enterEvent(QEvent*)
211 if (resizeMode() == ResizeOnHover)
212 setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
215 void StyledLabel::leaveEvent(QEvent*)
218 if (resizeMode() == ResizeOnHover)
219 setWrapMode(QTextOption::NoWrap);
222 void StyledLabel::mousePressEvent(QMouseEvent* event)
224 if (event->button() == Qt::LeftButton) {
225 Clickable click = _clickables.atCursorPos(posToCursor(event->localPos()));
227 emit clickableActivated(click);
231 void StyledLabel::setHoverMode(int start, int length)
233 if (_extraLayoutList.count() >= 1 && _extraLayoutList.first().start == start && _extraLayoutList.first().length == length)
236 QTextLayout::FormatRange range;
238 range.length = length;
239 range.format.setFontUnderline(true);
240 _extraLayoutList.clear();
241 _extraLayoutList << range;
243 setCursor(Qt::PointingHandCursor);
247 void StyledLabel::endHoverMode()
249 _extraLayoutList.clear();
250 setCursor(Qt::ArrowCursor);