#ifndef URLVIEW_H
#define URLVIEW_H
#include <QWidget>
#include <QTableView>
class UrlView : public QTableView
{
Q_OBJECT
public:
explicit UrlView(QWidget *parent = nullptr);
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
QString anchorAt(const QPoint &pos) const;
signals:
void linkActivated(QString link);
void linkHovered(QString link);
void linkUnhovered();
};
#endif // URLVIEW_H
#include "urlview.h"
#include <QStandardItemModel>
#include <QAbstractTextDocumentLayout>
#include <QHeaderView>
#include <QPainter>
#include <QScrollBar>
#include <QStyledItemDelegate>
#include <QTextDocument>
#include <QLabel>
#include <QTextBlock>
struct Date {
QString msg;
QString url;
QString urlTip;
};
QVector<Date> datas = {
{"this is %1 , is a very inter warfldjeo welrk3eo wsfm3ekih",
"https://www.runoob.com/", "cainiao"},
{"If you want to provide your users with an editable rich text editor, use "
"%1. If you want a text browser without hypertext navigation use",
"https://doc.qt.io/qt-5/qtextedit.html", "QTextEdit"},
{"this is %1 , is a very inter warfldjeo welrk3eo wsfm3ekih",
"https://www.runoob.com/", "cainiao"}};
class LinkableItemDelegate : public QStyledItemDelegate {
public:
explicit LinkableItemDelegate(QObject *parent = 0) {}
QString anchorAt(const QString& html,const QPoint &point) const {
QTextDocument doc;
doc.setTextWidth(360);
doc.setHtml(html);
auto textLayout = doc.documentLayout();
Q_ASSERT(textLayout != 0);
QPointF p = point - textPoint_;
return textLayout->anchorAt(p);
}
protected:
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const override{
painter->save();
QRect rect = option.rect;
painter->fillRect(QRect(rect.x() + 50, rect.y(), 300, 380),
QColor("#ff8833"));
QString text = datas[index.column()].msg;
text = text.arg(QString("<a href=\"%1\">%2</a>")
.arg(datas[index.column()].url)
.arg(datas[index.column()].urlTip));
QString html_ =
QString("<!DOCTYPE html><html><head><meta charset=\"utf-8\"></head> \
<body>\
<p style=\"color:rgb(255,0,0)\"> <font color=\"#00ff00\">%1. </font> \
%2 \
</p> \
</body></html>")
.arg(index.column() + 1)
.arg(text);
QRect textRect(rect.x() + 20, rect.y() + 400, 360, 100);
QTextDocument doc;
doc.setHtml(html_);
doc.setTextWidth(textRect.width());
textPoint_ = QPointF(20, 400);
painter->translate(textRect.x(), textRect.y());
doc.drawContents(painter);
// painter->drawText(textRect, Qt::AlignLeft | Qt::AlignTop |
// Qt::TextWordWrap,
// html);
painter->restore();
}
QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const override {
return QSize(400, 500);
}
private:
mutable QPointF textPoint_;
};
class LinkTableViewModel : public QAbstractTableModel {
public:
LinkTableViewModel(QObject *parent = 0) {}
int rowCount(const QModelIndex &parent) const override { return 1; }
int columnCount(const QModelIndex &parent) const override {
return datas.size();
}
QVariant data(const QModelIndex &index, int role) const override {
if(role == Qt::DisplayRole){
QString text = datas[index.column()].msg;
text = text.arg(QString("<a href=\"%1\">%2</a>")
.arg(datas[index.column()].url)
.arg(datas[index.column()].urlTip));
QString html =
QString("<!DOCTYPE html><html><head><meta charset=\"utf-8\"></head> \
<body>\
<p style=\"color:rgb(255,0,0)\"> <font color=\"#00ff00\">%1. </font> \
%2 \
</p> \
</body></html>")
.arg(index.column() + 1)
.arg(text);
return html;
}
return QVariant();
}
QVariant headerData(int section, Qt::Orientation orientation,
int role) const override {
if(role == Qt::DisplayRole){
return "aaa";
}
return QVariant();
}
Qt::ItemFlags flags(const QModelIndex &index) const override {
return QAbstractTableModel::flags(index);
}
};
UrlView::UrlView(QWidget *parent) : QTableView{parent} {
setMouseTracking(true);
setModel(new LinkTableViewModel(this));
setItemDelegate(new LinkableItemDelegate(this));
setShowGrid(false);
this->horizontalHeader()->setVisible(false);
this->verticalHeader()->setVisible(false);
setSelectionMode(QTableView::NoSelection);
resizeColumnsToContents();
resizeRowsToContents();
}
void UrlView::mousePressEvent(QMouseEvent *event) {
QString linkStr = anchorAt(event->pos());
if(linkStr.size() > 1){
emit linkActivated(linkStr);
}
}
void UrlView::mouseReleaseEvent(QMouseEvent *event) {}
void UrlView::mouseMoveEvent(QMouseEvent *event) {
if(anchorAt(event->pos()).size() > 1){
setCursor(Qt::OpenHandCursor);
}
else
{
setCursor(Qt::ArrowCursor);
}
}
QString UrlView::anchorAt(const QPoint &pos) const {
auto index = indexAt(pos);
if (index.isValid()) {
auto delegate = this->itemDelegateForIndex(index);
auto linkableDelegate = dynamic_cast<LinkableItemDelegate *>(delegate);
if (linkableDelegate != 0) {
auto itemRect = visualRect(index);
auto relativeClickPosition = pos - itemRect.topLeft();
QString html = model()->data(index, Qt::DisplayRole).toString();
return linkableDelegate->anchorAt(html,relativeClickPosition);
}
}
return "";
}