/src/ui/TextLabel.cpp

https://github.com/mujx/nheko · C++ · 118 lines · 92 code · 23 blank · 3 comment · 10 complexity · 2baa90860ff6335bbb15839c9a7acef1 MD5 · raw file

  1. #include "ui/TextLabel.h"
  2. #include <QAbstractTextDocumentLayout>
  3. #include <QDesktopServices>
  4. #include <QEvent>
  5. #include <QWheelEvent>
  6. #include "Utils.h"
  7. bool
  8. ContextMenuFilter::eventFilter(QObject *obj, QEvent *event)
  9. {
  10. if (event->type() == QEvent::MouseButtonPress) {
  11. emit contextMenuIsOpening();
  12. return true;
  13. }
  14. return QObject::eventFilter(obj, event);
  15. }
  16. TextLabel::TextLabel(QWidget *parent)
  17. : TextLabel(QString(), parent)
  18. {}
  19. TextLabel::TextLabel(const QString &text, QWidget *parent)
  20. : QTextBrowser(parent)
  21. {
  22. document()->setDefaultStyleSheet(QString("a {color: %1; }").arg(utils::linkColor()));
  23. setText(text);
  24. setOpenExternalLinks(true);
  25. // Make it look and feel like an ordinary label.
  26. setReadOnly(true);
  27. setFrameStyle(QFrame::NoFrame);
  28. QPalette pal = palette();
  29. pal.setColor(QPalette::Base, Qt::transparent);
  30. setPalette(pal);
  31. // Wrap anywhere but prefer words, adjust minimum height on the fly.
  32. setLineWrapMode(QTextEdit::WidgetWidth);
  33. setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
  34. connect(document()->documentLayout(),
  35. &QAbstractTextDocumentLayout::documentSizeChanged,
  36. this,
  37. &TextLabel::adjustHeight);
  38. document()->setDocumentMargin(0);
  39. setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
  40. setFixedHeight(0);
  41. connect(this, &TextLabel::linkActivated, this, &TextLabel::handleLinkActivation);
  42. auto filter = new ContextMenuFilter(this);
  43. installEventFilter(filter);
  44. connect(filter, &ContextMenuFilter::contextMenuIsOpening, this, [this]() {
  45. contextMenuRequested_ = true;
  46. });
  47. }
  48. void
  49. TextLabel::focusOutEvent(QFocusEvent *e)
  50. {
  51. QTextBrowser::focusOutEvent(e);
  52. // We keep the selection available for the context menu.
  53. if (contextMenuRequested_) {
  54. contextMenuRequested_ = false;
  55. return;
  56. }
  57. QTextCursor cursor = textCursor();
  58. cursor.clearSelection();
  59. setTextCursor(cursor);
  60. }
  61. void
  62. TextLabel::mousePressEvent(QMouseEvent *e)
  63. {
  64. link_ = (e->button() & Qt::LeftButton) ? anchorAt(e->pos()) : QString();
  65. QTextBrowser::mousePressEvent(e);
  66. }
  67. void
  68. TextLabel::mouseReleaseEvent(QMouseEvent *e)
  69. {
  70. if (e->button() & Qt::LeftButton && !link_.isEmpty() && anchorAt(e->pos()) == link_) {
  71. emit linkActivated(link_);
  72. return;
  73. }
  74. QTextBrowser::mouseReleaseEvent(e);
  75. }
  76. void
  77. TextLabel::wheelEvent(QWheelEvent *event)
  78. {
  79. event->ignore();
  80. }
  81. void
  82. TextLabel::handleLinkActivation(const QUrl &url)
  83. {
  84. auto parts = url.toString().split('/');
  85. auto defaultHandler = [](const QUrl &url) { QDesktopServices::openUrl(url); };
  86. if (url.host() != "matrix.to" || parts.isEmpty())
  87. return defaultHandler(url);
  88. try {
  89. using namespace mtx::identifiers;
  90. parse<User>(parts.last().toStdString());
  91. } catch (const std::exception &) {
  92. return defaultHandler(url);
  93. }
  94. emit userProfileTriggered(parts.last());
  95. }