diff --git a/src/TopRoomBar.cpp b/src/TopRoomBar.cpp
index 5fc6ab4a..a5d264c7 100644
--- a/src/TopRoomBar.cpp
+++ b/src/TopRoomBar.cpp
@@ -22,11 +22,11 @@
#include "MainWindow.h"
#include "TopRoomBar.h"
#include "Utils.h"
-#include "timeline/TimelineItem.h"
#include "ui/Avatar.h"
#include "ui/FlatButton.h"
#include "ui/Menu.h"
#include "ui/OverlayModal.h"
+#include "ui/TextLabel.h"
TopRoomBar::TopRoomBar(QWidget *parent)
: QWidget(parent)
diff --git a/src/timeline/TimelineItem.cpp b/src/timeline/TimelineItem.cpp
index b62437cd..9558c397 100644
--- a/src/timeline/TimelineItem.cpp
+++ b/src/timeline/TimelineItem.cpp
@@ -28,6 +28,7 @@
#include "Olm.h"
#include "ui/Avatar.h"
#include "ui/Painter.h"
+#include "ui/TextLabel.h"
#include "timeline/TimelineItem.h"
#include "timeline/widgets/AudioItem.h"
@@ -41,86 +42,6 @@
constexpr int MSG_RIGHT_MARGIN = 7;
constexpr int MSG_PADDING = 20;
-TextLabel::TextLabel(QWidget *parent)
- : TextLabel(QString(), parent)
-{}
-
-TextLabel::TextLabel(const QString &text, QWidget *parent)
- : QTextBrowser(parent)
-{
- document()->setDefaultStyleSheet(QString("a {color: %1; }").arg(utils::linkColor()));
-
- setText(text);
- setOpenExternalLinks(true);
-
- // Make it look and feel like an ordinary label.
- setReadOnly(true);
- setFrameStyle(QFrame::NoFrame);
- QPalette pal = palette();
- pal.setColor(QPalette::Base, Qt::transparent);
- setPalette(pal);
-
- // Wrap anywhere but prefer words, adjust minimum height on the fly.
- setLineWrapMode(QTextEdit::WidgetWidth);
- setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
- connect(document()->documentLayout(),
- &QAbstractTextDocumentLayout::documentSizeChanged,
- this,
- &TextLabel::adjustHeight);
- document()->setDocumentMargin(0);
-
- setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
- setFixedHeight(0);
-
- connect(this, &TextLabel::linkActivated, this, [](const QUrl &url) {
- auto parts = url.toString().split('/');
- auto defaultHandler = [](const QUrl &url) { QDesktopServices::openUrl(url); };
-
- if (url.host() != "matrix.to" || parts.isEmpty())
- return defaultHandler(url);
-
- try {
- using namespace mtx::identifiers;
- parse<User>(parts.last().toStdString());
- } catch (const std::exception &) {
- return defaultHandler(url);
- }
-
- auto user_id = parts.last();
- auto room_id = ChatPage::instance()->currentRoom();
-
- MainWindow::instance()->openUserProfile(user_id, room_id);
- });
-}
-
-void
-TextLabel::focusOutEvent(QFocusEvent *e)
-{
- QTextBrowser::focusOutEvent(e);
-
- QTextCursor cursor = textCursor();
- cursor.clearSelection();
- setTextCursor(cursor);
-}
-
-void
-TextLabel::mousePressEvent(QMouseEvent *e)
-{
- link_ = (e->button() & Qt::LeftButton) ? anchorAt(e->pos()) : QString();
- QTextBrowser::mousePressEvent(e);
-}
-
-void
-TextLabel::mouseReleaseEvent(QMouseEvent *e)
-{
- if (e->button() & Qt::LeftButton && !link_.isEmpty() && anchorAt(e->pos()) == link_) {
- emit linkActivated(link_);
- return;
- }
-
- QTextBrowser::mouseReleaseEvent(e);
-}
-
StatusIndicator::StatusIndicator(QWidget *parent)
: QWidget(parent)
{
@@ -680,6 +601,11 @@ TimelineItem::generateBody(const QString &body)
body_ = new TextLabel(replaceEmoji(body), this);
body_->setFont(font_);
body_->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction);
+
+ connect(body_, &TextLabel::userProfileTriggered, this, [](const QString &user_id) {
+ MainWindow::instance()->openUserProfile(user_id,
+ ChatPage::instance()->currentRoom());
+ });
}
// The username/timestamp is displayed along with the message body.
diff --git a/src/timeline/TimelineItem.h b/src/timeline/TimelineItem.h
index b2e6c8b5..ae486257 100644
--- a/src/timeline/TimelineItem.h
+++ b/src/timeline/TimelineItem.h
@@ -17,7 +17,6 @@
#pragma once
-#include <QAbstractTextDocumentLayout>
#include <QApplication>
#include <QDateTime>
#include <QHBoxLayout>
@@ -25,9 +24,6 @@
#include <QLayout>
#include <QPainter>
#include <QSettings>
-#include <QStyle>
-#include <QStyleOption>
-#include <QTextBrowser>
#include <QTimer>
#include "AvatarProvider.h"
@@ -43,6 +39,7 @@ class AudioItem;
class VideoItem;
class FileItem;
class Avatar;
+class TextLabel;
enum class StatusIndicatorState
{
@@ -96,32 +93,6 @@ signals:
void eventRetrieved(const nlohmann::json &);
};
-class TextLabel : public QTextBrowser
-{
- Q_OBJECT
-
-public:
- TextLabel(const QString &text, QWidget *parent = nullptr);
- TextLabel(QWidget *parent = nullptr);
-
- void wheelEvent(QWheelEvent *event) override { event->ignore(); }
- void clearLinks() { link_.clear(); }
-
-protected:
- void mousePressEvent(QMouseEvent *e) override;
- void mouseReleaseEvent(QMouseEvent *e) override;
- void focusOutEvent(QFocusEvent *e) override;
-
-private slots:
- void adjustHeight(const QSizeF &size) { setFixedHeight(size.height()); }
-
-signals:
- void linkActivated(const QUrl &link);
-
-private:
- QString link_;
-};
-
class UserProfileFilter : public QObject
{
Q_OBJECT
diff --git a/src/ui/TextLabel.cpp b/src/ui/TextLabel.cpp
new file mode 100644
index 00000000..85267674
--- /dev/null
+++ b/src/ui/TextLabel.cpp
@@ -0,0 +1,95 @@
+#include "ui/TextLabel.h"
+
+#include <QAbstractTextDocumentLayout>
+#include <QDesktopServices>
+#include <QEvent>
+#include <QWheelEvent>
+
+#include "Utils.h"
+
+TextLabel::TextLabel(QWidget *parent)
+ : TextLabel(QString(), parent)
+{}
+
+TextLabel::TextLabel(const QString &text, QWidget *parent)
+ : QTextBrowser(parent)
+{
+ document()->setDefaultStyleSheet(QString("a {color: %1; }").arg(utils::linkColor()));
+
+ setText(text);
+ setOpenExternalLinks(true);
+
+ // Make it look and feel like an ordinary label.
+ setReadOnly(true);
+ setFrameStyle(QFrame::NoFrame);
+ QPalette pal = palette();
+ pal.setColor(QPalette::Base, Qt::transparent);
+ setPalette(pal);
+
+ // Wrap anywhere but prefer words, adjust minimum height on the fly.
+ setLineWrapMode(QTextEdit::WidgetWidth);
+ setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
+ connect(document()->documentLayout(),
+ &QAbstractTextDocumentLayout::documentSizeChanged,
+ this,
+ &TextLabel::adjustHeight);
+ document()->setDocumentMargin(0);
+
+ setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ setFixedHeight(0);
+
+ connect(this, &TextLabel::linkActivated, this, &TextLabel::handleLinkActivation);
+}
+
+void
+TextLabel::focusOutEvent(QFocusEvent *e)
+{
+ QTextBrowser::focusOutEvent(e);
+
+ QTextCursor cursor = textCursor();
+ cursor.clearSelection();
+ setTextCursor(cursor);
+}
+
+void
+TextLabel::mousePressEvent(QMouseEvent *e)
+{
+ link_ = (e->button() & Qt::LeftButton) ? anchorAt(e->pos()) : QString();
+ QTextBrowser::mousePressEvent(e);
+}
+
+void
+TextLabel::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (e->button() & Qt::LeftButton && !link_.isEmpty() && anchorAt(e->pos()) == link_) {
+ emit linkActivated(link_);
+ return;
+ }
+
+ QTextBrowser::mouseReleaseEvent(e);
+}
+
+void
+TextLabel::wheelEvent(QWheelEvent *event)
+{
+ event->ignore();
+}
+
+void
+TextLabel::handleLinkActivation(const QUrl &url)
+{
+ auto parts = url.toString().split('/');
+ auto defaultHandler = [](const QUrl &url) { QDesktopServices::openUrl(url); };
+
+ if (url.host() != "matrix.to" || parts.isEmpty())
+ return defaultHandler(url);
+
+ try {
+ using namespace mtx::identifiers;
+ parse<User>(parts.last().toStdString());
+ } catch (const std::exception &) {
+ return defaultHandler(url);
+ }
+
+ emit userProfileTriggered(parts.last());
+}
diff --git a/src/ui/TextLabel.h b/src/ui/TextLabel.h
new file mode 100644
index 00000000..da6e9c4b
--- /dev/null
+++ b/src/ui/TextLabel.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <QSize>
+#include <QString>
+#include <QTextBrowser>
+#include <QUrl>
+
+class QMouseEvent;
+class QFocusEvent;
+class QWheelEvent;
+
+class TextLabel : public QTextBrowser
+{
+ Q_OBJECT
+
+public:
+ TextLabel(const QString &text, QWidget *parent = nullptr);
+ TextLabel(QWidget *parent = nullptr);
+
+ void wheelEvent(QWheelEvent *event) override;
+ void clearLinks() { link_.clear(); }
+
+protected:
+ void mousePressEvent(QMouseEvent *e) override;
+ void mouseReleaseEvent(QMouseEvent *e) override;
+ void focusOutEvent(QFocusEvent *e) override;
+
+private slots:
+ void adjustHeight(const QSizeF &size) { setFixedHeight(size.height()); }
+ void handleLinkActivation(const QUrl &link);
+
+signals:
+ void userProfileTriggered(const QString &user_id);
+ void linkActivated(const QUrl &link);
+
+private:
+ QString link_;
+};
|