1 /***************************************************************************
2 * Copyright (C) 2005-2018 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 _alignment(Qt::AlignVCenter|Qt::AlignLeft)
33 setMouseTracking(true);
35 QTextOption opt = _layout.textOption();
36 opt.setWrapMode(_wrapMode);
37 opt.setAlignment(_alignment);
38 _layout.setTextOption(opt);
42 void StyledLabel::setCustomFont(const QFont &font)
45 _layout.setFont(font);
46 setText(_layout.text());
50 void StyledLabel::setWrapMode(QTextOption::WrapMode mode)
52 if (_wrapMode == mode)
56 QTextOption opt = _layout.textOption();
57 opt.setWrapMode(mode);
58 _layout.setTextOption(opt);
64 void StyledLabel::setAlignment(Qt::Alignment alignment)
66 if (_alignment == alignment)
69 _alignment = alignment;
70 QTextOption opt = _layout.textOption();
71 opt.setAlignment(alignment);
72 _layout.setTextOption(opt);
78 void StyledLabel::setResizeMode(ResizeMode mode)
80 if (_resizeMode == mode)
84 if (mode == DynamicResize)
85 setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
87 setWrapMode(QTextOption::NoWrap);
91 void StyledLabel::resizeEvent(QResizeEvent *event)
93 QFrame::resizeEvent(event);
99 QSize StyledLabel::sizeHint() const
105 void StyledLabel::updateSizeHint()
108 int padding = frameWidth() * 2;
109 sh = _layout.boundingRect().size().toSize() + QSize(padding, padding);
111 if (_sizeHint != sh) {
118 void StyledLabel::setText(const QString &text)
120 UiStyle *style = GraphicalUi::uiStyle();
122 UiStyle::StyledString sstr = style->styleString(style->mircToInternal(text), UiStyle::FormatType::PlainMsg);
123 QList<QTextLayout::FormatRange> layoutList = style->toTextLayoutList(sstr.formatList, sstr.plainText.length(), UiStyle::MessageLabel::None);
125 // Use default font rather than the style's
126 QTextLayout::FormatRange fmtRange;
127 fmtRange.format.setFont(font());
129 fmtRange.length = sstr.plainText.length();
130 layoutList << fmtRange;
133 _clickables = ClickableList::fromString(sstr.plainText);
134 foreach(Clickable click, _clickables) {
135 if (click.type() == Clickable::Url) {
136 QTextLayout::FormatRange range;
137 range.start = click.start();
138 range.length = click.length();
139 range.format.setForeground(palette().link());
144 _layout.setText(sstr.plainText);
145 _layout.setAdditionalFormats(layoutList);
153 void StyledLabel::updateToolTip()
155 if (frameRect().width() - 2*frameWidth() < _layout.minimumWidth())
156 setToolTip(QString("<qt>%1</qt>").arg(_layout.text().toHtmlEscaped())); // only rich text gets wordwrapped!
158 setToolTip(QString());
162 void StyledLabel::layout()
165 qreal w = contentsRect().width();
167 _layout.beginLayout();
169 QTextLine line = _layout.createLine();
172 line.setLineWidth(w);
173 line.setPosition(QPointF(0, h));
184 void StyledLabel::paintEvent(QPaintEvent *e)
186 QFrame::paintEvent(e);
187 QPainter painter(this);
189 qreal y = contentsRect().y() + (contentsRect().height() - _layout.boundingRect().height()) / 2;
190 _layout.draw(&painter, QPointF(contentsRect().x(), y), _extraLayoutList);
194 int StyledLabel::posToCursor(const QPointF &pos)
196 if (pos.y() < 0 || pos.y() > height())
199 for (int l = _layout.lineCount() - 1; l >= 0; l--) {
200 QTextLine line = _layout.lineAt(l);
201 if (pos.y() >= line.y()) {
202 return line.xToCursor(pos.x(), QTextLine::CursorOnCharacter);
209 void StyledLabel::mouseMoveEvent(QMouseEvent *event)
211 if (event->buttons() == Qt::NoButton) {
212 Clickable click = _clickables.atCursorPos(posToCursor(event->localPos()));
214 setHoverMode(click.start(), click.length());
221 void StyledLabel::enterEvent(QEvent *)
223 if (resizeMode() == ResizeOnHover)
224 setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
228 void StyledLabel::leaveEvent(QEvent *)
231 if (resizeMode() == ResizeOnHover)
232 setWrapMode(QTextOption::NoWrap);
236 void StyledLabel::mousePressEvent(QMouseEvent *event)
238 if (event->button() == Qt::LeftButton) {
239 Clickable click = _clickables.atCursorPos(posToCursor(event->localPos()));
241 emit clickableActivated(click);
246 void StyledLabel::setHoverMode(int start, int length)
248 if (_extraLayoutList.count() >= 1 && _extraLayoutList.first().start == start && _extraLayoutList.first().length == length)
251 QTextLayout::FormatRange range;
253 range.length = length;
254 range.format.setFontUnderline(true);
255 _extraLayoutList.clear();
256 _extraLayoutList << range;
258 setCursor(Qt::PointingHandCursor);
263 void StyledLabel::endHoverMode()
265 _extraLayoutList.clear();
266 setCursor(Qt::ArrowCursor);