How to open url in QTableView

What is the best way to present clickable URLs in a QTableView (or QTreeView , QListView , etc.)

Given a QStandardItemModel , where some columns contain text with URLs, I would like them to become clickable and then handle the click using QDesktopServices::openURL()

I was hoping there would be an easy way to use the QLabel textInteraction flags and insert them into the table. I cannot believe that there is no simpler way to handle this. I really hope I missed something.

+6
c ++ url qt qt4 qtableview
source share
3 answers

You will need to create a delegate to create the picture. The code should look something like this:

 void RenderLinkDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const { QString text = index.data(Qt::DisplayRole).toString(); if (text.isEmpty()) return; painter->save(); // I only wanted it for mouse over, but you'll probably want to remove // this condition if (option.state & QStyle::State_MouseOver) { QFont font = option.font; font.setUnderline(true); painter->setFont(font); painter->setPen(option.palette.link().color()); } painter->drawText(option.rect, Qt::AlignLeft | Qt::AlignVCenter, text); painter->restore(); } 
+5
source share

Well, you can use delegates to render rich text in qtableview with custom delegates overriding the drawing method, for example:

 void CHtmlDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionViewItemV4 opt(option); QLabel *label = new QLabel; label->setText(index.data().toString()); label->setTextFormat(Qt::RichText); label->setGeometry(option.rect); label->setStyleSheet("QLabel { background-color : transparent; }"); painter->translate(option.rect.topLeft()); label->render(painter); painter->translate(-option.rect.topLeft()); } 

However, he will not make interactive hyperlink links.

You can use the following hack for this. Reinstall the setModel method in your table / list view and use setIndexWidget.

 void MyView::setModel(QAbstractItemModel *m) { if (!m) return; QTableView::setModel(m); const int rows = model()->rowCount(); for (int i = 0; i < rows; ++i) { QModelIndex idx = model()->index(i, 1); QLabel *label = new QLabel; label->setTextFormat(Qt::RichText); label->setText(model()->data(idx, CTableModel::HtmlRole).toString()); label->setOpenExternalLinks(true); setIndexWidget(idx, label); } } 

In the above example, I will replace column 1 with qlabels. Note that you need to invalidate the display role in the model to avoid data duplication.

In any case, I will be interested in the best solution based on delegates.

+2
source share

Unfortunately, it is not so easy to make a QLabel with setOpenExternalLinks() when using QTableView (as opposed to using QTableWidget ). There are no magic two lines of code that you can invoke and complete the task.

  • use delegate
  • set delegate to table column
  • use QTextDocument in combination with setHTML() to display html link
  • this means your model needs to be provided with an HTML fragment containing a href
  • compute link geometry and provide event handlers to intercept the mouse
    • change the cursor when it is on the link
    • perform an action when a link is clicked
  • what a mess :( i want painter->setWidgetToCell()

-

 void LabelColumnItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if( option.state & QStyle::State_Selected ) painter->fillRect( option.rect, option.palette.highlight() ); painter->save(); QTextDocument document; // <---- RichText document.setTextWidth(option.rect.width()); QVariant value = index.data(Qt::DisplayRole); if (value.isValid() && !value.isNull()) { document.setHtml(value.toString()); // <---- make sure model contains html painter->translate(option.rect.topLeft()); document.drawContents(painter); } painter->restore(); } 
0
source share

All Articles