From 6ce1966d5d3070ad461a976a2bee7cc28e8b9149 Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Tue, 25 Aug 2009 21:48:26 +0200 Subject: [PATCH] Make URLs (and channel names!) in the topic widget clickable again This time properly, including on-hover underline and proper coloring. Also, we now use the widget font rather than the ChatView font for the topic. --- src/qtui/topicwidget.cpp | 8 +++- src/qtui/topicwidget.h | 1 + src/uisupport/styledlabel.cpp | 82 ++++++++++++++++++++++++++++++++++- src/uisupport/styledlabel.h | 17 ++++++-- 4 files changed, 102 insertions(+), 6 deletions(-) diff --git a/src/qtui/topicwidget.cpp b/src/qtui/topicwidget.cpp index 8a49d275..2f8f5fa4 100644 --- a/src/qtui/topicwidget.cpp +++ b/src/qtui/topicwidget.cpp @@ -30,8 +30,9 @@ TopicWidget::TopicWidget(QWidget *parent) ui.setupUi(this); ui.topicEditButton->setIcon(SmallIcon("edit-rename")); ui.topicLineEdit->setWordWrapEnabled(true); - ui.topicLineEdit->installEventFilter(this); + + connect(ui.topicLabel, SIGNAL(clickableActivated(Clickable)), SLOT(clickableActivated(Clickable))); } void TopicWidget::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { @@ -56,6 +57,11 @@ void TopicWidget::setTopic(const QString &newtopic) { switchPlain(); } +void TopicWidget::clickableActivated(const Clickable &click) { + NetworkId networkId = selectionModel()->currentIndex().data(NetworkModel::NetworkIdRole).value(); + click.activate(networkId, _topic); +} + void TopicWidget::on_topicLineEdit_textEntered() { QModelIndex currentIdx = currentIndex(); if(currentIdx.isValid() && currentIdx.data(NetworkModel::BufferTypeRole) == BufferInfo::ChannelBuffer) { diff --git a/src/qtui/topicwidget.h b/src/qtui/topicwidget.h index 76e68f19..18eae860 100644 --- a/src/qtui/topicwidget.h +++ b/src/qtui/topicwidget.h @@ -44,6 +44,7 @@ private slots: void on_topicEditButton_clicked(); void switchEditable(); void switchPlain(); + void clickableActivated(const Clickable &); private: Ui::TopicWidget ui; diff --git a/src/uisupport/styledlabel.cpp b/src/uisupport/styledlabel.cpp index 13690df3..372b9bbe 100644 --- a/src/uisupport/styledlabel.cpp +++ b/src/uisupport/styledlabel.cpp @@ -32,6 +32,8 @@ StyledLabel::StyledLabel(QWidget *parent) _alignment(Qt::AlignVCenter|Qt::AlignLeft), _toolTipEnabled(true) { + setMouseTracking(true); + QTextOption opt = _layout.textOption(); opt.setWrapMode(_wrapMode); opt.setAlignment(_alignment); @@ -89,10 +91,31 @@ void StyledLabel::setText(const QString &text) { UiStyle::StyledString sstr = style->styleString(style->mircToInternal(text), UiStyle::PlainMsg); QList layoutList = style->toTextLayoutList(sstr.formatList, sstr.plainText.length(), 0); + // Use default font rather than the style's + QTextLayout::FormatRange fmtRange; + fmtRange.format.setFont(font()); + fmtRange.start = 0; + fmtRange.length = sstr.plainText.length(); + layoutList << fmtRange; + + // Mark URLs + _clickables = ClickableList::fromString(sstr.plainText); + foreach(Clickable click, _clickables) { + if(click.type() == Clickable::Url) { + QTextLayout::FormatRange range; + range.start = click.start(); + range.length = click.length(); + range.format.setForeground(palette().link()); + layoutList << range; + } + } + _layout.setText(sstr.plainText); _layout.setAdditionalFormats(layoutList); layout(); + + endHoverMode(); } void StyledLabel::updateToolTip() { @@ -126,5 +149,62 @@ void StyledLabel::paintEvent(QPaintEvent *) { QPainter painter(this); qreal y = (frameRect().height() - _layout.boundingRect().height()) / 2; - _layout.draw(&painter, QPointF(0, y), QVector()); + _layout.draw(&painter, QPointF(0, y), _extraLayoutList); +} + +int StyledLabel::posToCursor(const QPointF &pos) { + if(pos.y() < 0 || pos.y() > height()) + return -1; + + for(int l = _layout.lineCount() - 1; l >= 0; l--) { + QTextLine line = _layout.lineAt(l); + if(pos.y() >= line.y()) { + return line.xToCursor(pos.x(), QTextLine::CursorOnCharacter); + } + } + return -1; +} + +void StyledLabel::mouseMoveEvent(QMouseEvent *event) { + if(event->buttons() == Qt::NoButton) { + Clickable click = _clickables.atCursorPos(posToCursor(event->posF())); + if(click.isValid()) + setHoverMode(click.start(), click.length()); + else + endHoverMode(); + } +} + +void StyledLabel::leaveEvent(QEvent *) { + endHoverMode(); } + +void StyledLabel::mousePressEvent(QMouseEvent *event) { + if(event->button() == Qt::LeftButton) { + Clickable click = _clickables.atCursorPos(posToCursor(event->posF())); + if(click.isValid()) + emit clickableActivated(click); + } +} + +void StyledLabel::setHoverMode(int start, int length) { + if(_extraLayoutList.count() >= 1 && _extraLayoutList.first().start == start && _extraLayoutList.first().length == length) + return; + + QTextLayout::FormatRange range; + range.start = start; + range.length = length; + range.format.setFontUnderline(true); + _extraLayoutList.clear(); + _extraLayoutList << range; + + setCursor(Qt::PointingHandCursor); + update(); +} + +void StyledLabel::endHoverMode() { + _extraLayoutList.clear(); + setCursor(Qt::ArrowCursor); + update(); +} + diff --git a/src/uisupport/styledlabel.h b/src/uisupport/styledlabel.h index 4eefb6a0..de412a87 100644 --- a/src/uisupport/styledlabel.h +++ b/src/uisupport/styledlabel.h @@ -23,6 +23,7 @@ #include +#include "clickable.h" #include "uistyle.h" class StyledLabel : public QFrame { @@ -45,27 +46,35 @@ public: inline bool toolTipEnabled() const { return _toolTipEnabled; } void setToolTipEnabled(bool); +signals: + void clickableActivated(const Clickable &click); + protected: virtual void paintEvent(QPaintEvent *event); virtual void resizeEvent(QResizeEvent *event); + virtual void leaveEvent(QEvent *); + virtual void mouseMoveEvent(QMouseEvent *event); + virtual void mousePressEvent(QMouseEvent *event); - //void mouseMoveEvent(QMouseEvent *event); - //void mousePressEvent(QMouseEvent *event); - //void mouseReleaseEvent(QMouseEvent *event); - //void mouseDoubleClickEvent(QMouseEvent *event); + int posToCursor(const QPointF &pos); private: QSize _sizeHint; QTextOption::WrapMode _wrapMode; Qt::Alignment _alignment; QTextLayout _layout; + ClickableList _clickables; bool _toolTipEnabled; QList _layoutList; + QVector _extraLayoutList; void layout(); void updateSizeHint(); void updateToolTip(); + + void setHoverMode(int start, int length); + void endHoverMode(); }; #endif -- 2.20.1