Skip to content

Commit

Permalink
Support CTRL+Click for opening links in attribute table
Browse files Browse the repository at this point in the history
  • Loading branch information
manisandro committed Jul 30, 2021
1 parent 1bd8f5c commit b5bdb37
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 3 deletions.
11 changes: 11 additions & 0 deletions python/core/auto_generated/qgsstringutils.sip.in
Expand Up @@ -279,6 +279,17 @@ links.
:return: string with inserted links

.. versionadded:: 3.0
%End

static bool isUrl( const QString &string );
%Docstring
Returns whether the string is a URL (http,https,ftp,file)

:param string: the string to check

:return: whether the string is an URL

.. versionadded:: 3.22
%End

static QString wordWrap( const QString &string, int length, bool useMaxLineLength = true, const QString &customDelimiter = QString() );
Expand Down
5 changes: 5 additions & 0 deletions src/core/qgsstringutils.cpp
Expand Up @@ -563,6 +563,11 @@ QString QgsStringUtils::insertLinks( const QString &string, bool *foundLinks )
return converted;
}

bool QgsStringUtils::isUrl( const QString &string )
{
return QRegularExpression( "^(http|https|ftp|file)://\\S+$" ).match( string ).hasMatch();
}

QString QgsStringUtils::htmlToMarkdown( const QString &html )
{
// Any changes in this function must be copied to qgscrashreport.cpp too
Expand Down
8 changes: 8 additions & 0 deletions src/core/qgsstringutils.h
Expand Up @@ -277,6 +277,14 @@ class CORE_EXPORT QgsStringUtils
*/
static QString insertLinks( const QString &string, bool *foundLinks = nullptr );

/**
* Returns whether the string is a URL (http,https,ftp,file)
* \param string the string to check
* \returns whether the string is an URL
* \since QGIS 3.22
*/
static bool isUrl( const QString &string );

/**
* Automatically wraps a \a string by inserting new line characters at appropriate locations in the string.
*
Expand Down
32 changes: 29 additions & 3 deletions src/gui/attributetable/qgsattributetablemodel.cpp
Expand Up @@ -40,6 +40,7 @@
#include "qgsfieldmodel.h"
#include "qgstexteditwidgetfactory.h"
#include "qgsexpressioncontextutils.h"
#include "qgsstringutils.h"
#include "qgsvectorlayerutils.h"
#include "qgsvectorlayercache.h"

Expand Down Expand Up @@ -698,17 +699,29 @@ QVariant QgsAttributeTableModel::data( const QModelIndex &index, int role ) cons
}

QVariant val = mFeat.attribute( fieldId );
bool isLink = val.type() == QVariant::String && QgsStringUtils::isUrl( val.toString() );

switch ( role )
{
case Qt::DisplayRole:
case Qt::ToolTipRole:
return mFieldFormatters.at( index.column() )->representValue( mLayer,
fieldId,
mWidgetConfigs.at( index.column() ),
mAttributeWidgetCaches.at( index.column() ),
val );

case Qt::ToolTipRole:
{
QString tooltip = mFieldFormatters.at( index.column() )->representValue( mLayer,
fieldId,
mWidgetConfigs.at( index.column() ),
mAttributeWidgetCaches.at( index.column() ),
val );
if ( isLink )
{
tooltip = tr( "%1 (Ctrl+click to open)" ).arg( tooltip );
}
return tooltip;
}
case Qt::EditRole:
return val;

Expand Down Expand Up @@ -746,14 +759,27 @@ QVariant QgsAttributeTableModel::data( const QModelIndex &index, int role ) cons
#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
if ( role == Qt::TextColorRole && style.validTextColor() )
#else
if ( role == Qt::ForegroundRole && style.validTextColor() )
if ( role == Qt::ForegroundRole )
#endif
return style.textColor();
if ( role == Qt::DecorationRole )
return style.icon();
if ( role == Qt::FontRole )
return style.font();
}
else if ( isLink )
{
if ( role == Qt::ForegroundRole )
{
return QColor( Qt::blue );
}
else if ( role == Qt::FontRole )
{
QFont font;
font.setUnderline( true );
return font;
}
}

return QVariant();
}
Expand Down
15 changes: 15 additions & 0 deletions src/gui/attributetable/qgsattributetableview.cpp
Expand Up @@ -13,6 +13,7 @@
* *
***************************************************************************/

#include <QDesktopServices>
#include <QKeyEvent>
#include <QHeaderView>
#include <QMenu>
Expand All @@ -34,6 +35,7 @@
#include "qgsfeatureselectionmodel.h"
#include "qgsmaplayeractionregistry.h"
#include "qgsfeatureiterator.h"
#include "qgsstringutils.h"
#include "qgsgui.h"

QgsAttributeTableView::QgsAttributeTableView( QWidget *parent )
Expand Down Expand Up @@ -304,6 +306,19 @@ void QgsAttributeTableView::mouseReleaseEvent( QMouseEvent *event )
setSelectionMode( QAbstractItemView::NoSelection );
QTableView::mouseReleaseEvent( event );
setSelectionMode( QAbstractItemView::ExtendedSelection );
if ( event->modifiers() == Qt::ControlModifier )
{
QModelIndex index = indexAt( event->pos() );
QVariant data = model()->data( index, Qt::DisplayRole );
if ( data.type() == QVariant::String )
{
QString textVal = data.toString();
if ( QgsStringUtils::isUrl( textVal ) )
{
QDesktopServices::openUrl( QUrl( textVal ) );
}
}
}
}

void QgsAttributeTableView::mouseMoveEvent( QMouseEvent *event )
Expand Down

0 comments on commit b5bdb37

Please sign in to comment.