QAbstractTableModel subclass with hyperlink
-
Does anybody know of an existing subclass of QAbstractTableModel and/or its delegate, which is designed to allow rich text in the table cells (for hyperlinks)? Preferably also with sorting that works as expected (on the text shown and not on the url of the hyperlink). Just wanted to see if I can save myself the trouble of writing it if something like this already existed.
Thanks.
-
I've actually done this quite literally for a column of hyperlinks that open in the default web browser when clicked. It doesn't actually need any extra functionality in the model, just a delegate and a proxy model. The following is a fully working example:
main.cpp
@
#include <QtCore>
#include <QtGui>#include <tablemodel.h>
#include <richtextdelegate.h>
#include <richtextproxy.h>int main(int argc, char *argv[])
{
QApplication a(argc, argv);RichTextDelegate delegate; TableModel model; RichTextProxy proxy; proxy.setSourceModel(&model); QTableView view; view.setModel(&proxy); delegate.setTableView(&view); view.setItemDelegate(&delegate); view.setSortingEnabled(true); view.show(); return a.exec();
}
@tablemodel.h
@
#ifndef TABLEMODEL_H
#define TABLEMODEL_H#include <QAbstractTableModel>
#include <QVariant>class TableModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit TableModel(QObject *parent = 0);
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
};#endif // TABLEMODEL_H
@tablemodel.cpp
@
#include "tablemodel.h"TableModel::TableModel(QObject *parent) :
QAbstractTableModel(parent)
{
}int TableModel::rowCount(const QModelIndex &parent) const {
Q_UNUSED(parent);
return 10;
}int TableModel::columnCount(const QModelIndex &parent) const {
Q_UNUSED(parent);
return 10;
}QVariant TableModel::data(const QModelIndex &index, int role) const {
if(!index.isValid() || role!=Qt::DisplayRole) return QVariant();return QString("<a href='http://some.url/?row=%1&col=%2'>(%1,%2)</a>").arg(index.row()).arg(index.column());
}
@richtextdelegate.h
@
#ifndef RICHTEXTDELEGATE_H
#define RICHTEXTDELEGATE_H#include <QItemDelegate>
#include <QTableView>class RichTextDelegate : public QItemDelegate
{
Q_OBJECT
public:
explicit RichTextDelegate(QObject *parent = 0);
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void setTableView(QTableView *view){ this->view=view; }private:
QTableView *view;
};#endif // RICHTEXTDELEGATE_H
@richtextdelegate.cpp
@
#include "richtextdelegate.h"#include <QLabel>
RichTextDelegate::RichTextDelegate(QObject *parent) :
QItemDelegate(parent)
{}void RichTextDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {
Q_UNUSED(painter);
Q_UNUSED(option);if(view->indexWidget(index)!=0) return; QLabel *label=new QLabel; label->setTextFormat(Qt::RichText); label->setTextInteractionFlags(Qt::TextBrowserInteraction); label->setOpenExternalLinks(true); label->setText(index.data().toString()); view->setIndexWidget(index, label);
}
@richtextproxy.h
@
#ifndef RICHTEXTPROXY_H
#define RICHTEXTPROXY_H#include <QSortFilterProxyModel>
class RichTextProxy : public QSortFilterProxyModel
{
Q_OBJECT
public:
explicit RichTextProxy(QObject *parent = 0);protected:
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;};
#endif // RICHTEXTPROXY_H
@richtextproxy.cpp
@
#include "richtextproxy.h"
#include <QTextDocument>RichTextProxy::RichTextProxy(QObject *parent) :
QSortFilterProxyModel(parent)
{}bool RichTextProxy::lessThan(const QModelIndex &left, const QModelIndex &right) const {
QTextDocument doc; doc.setHtml(left.data().toString()); QString leftText=doc.toPlainText(); doc.setHtml(right.data().toString()); QString rightText=doc.toPlainText(); return leftText<rightText;
}
@Sorry for the crazy long post ;o) Basically the delegate just sets a QLabel for each cell (via the paint function) which acts as the rich text renderer. The proxy model uses QTextDocument to convert the rich text data to plain text (i.e. strip the markup) and then do the less than comparison. Hope this helps ;o)