[mesh] [feature] allow to choose different vector and scalar dataset

This commit is contained in:
Peter Petrik 2018-08-28 16:27:59 +02:00 committed by Nyall Dawson
parent 3f85938479
commit f0ede773c2
13 changed files with 979 additions and 218 deletions

View File

@ -526,8 +526,10 @@
<file>themes/default/propertyicons/locale.svg</file>
<file>themes/default/propertyicons/map_tools.svg</file>
<file>themes/default/propertyicons/meshcontours.svg</file>
<file>themes/default/propertyicons/meshcontoursoff.svg</file>
<file>themes/default/propertyicons/meshframe.svg</file>
<file>themes/default/propertyicons/meshvectors.svg</file>
<file>themes/default/propertyicons/meshvectorsoff.svg</file>
<file>themes/default/propertyicons/metadata.svg</file>
<file>themes/default/propertyicons/network_and_proxy.svg</file>
<file>themes/default/propertyicons/overlay.svg</file>

View File

@ -0,0 +1,200 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="meshcontoursoff.svg">
<defs
id="defs4">
<linearGradient
inkscape:collect="always"
id="linearGradient907">
<stop
style="stop-color:#b3b3b3;stop-opacity:1;"
offset="0"
id="stop903" />
<stop
style="stop-color:#b3b3b3;stop-opacity:0;"
offset="1"
id="stop905" />
</linearGradient>
<marker
inkscape:stockid="TriangleOutM"
orient="auto"
refY="0.0"
refX="0.0"
id="TriangleOutM"
style="overflow:visible">
<path
id="path3940"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
transform="scale(0.4)" />
</marker>
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Send"
style="overflow:visible;">
<path
id="path3810"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mend"
style="overflow:visible;">
<path
id="path3804"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Lend"
style="overflow:visible;">
<path
id="path3816"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) rotate(180) translate(1,0)" />
</marker>
<marker
inkscape:stockid="TriangleOutL"
orient="auto"
refY="0.0"
refX="0.0"
id="TriangleOutL"
style="overflow:visible">
<path
id="path3937"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
transform="scale(0.8)" />
</marker>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 8 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="16 : 8 : 1"
inkscape:persp3d-origin="8 : 5.3333333 : 1"
id="perspective3771" />
<linearGradient
id="linearGradient3755">
<stop
id="stop3767"
offset="0"
style="stop-color:#0000ff;stop-opacity:0.50196081;" />
<stop
id="stop3765"
offset="0.34999999"
style="stop-color:#00ffff;stop-opacity:0.50196081;" />
<stop
id="stop3763"
offset="0.5"
style="stop-color:#00ff00;stop-opacity:0.50196081;" />
<stop
style="stop-color:#ffff00;stop-opacity:0.50196081;"
offset="0.64999998"
id="stop3769" />
<stop
style="stop-color:#ff0000;stop-opacity:0.50980395;"
offset="1"
id="stop3759" />
</linearGradient>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Fade to Black or White"
id="filter1005">
<feColorMatrix
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"
id="feColorMatrix1003"
result="fbSourceGraphic" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
id="feColorMatrix1039" />
<feColorMatrix
id="feColorMatrix1041"
values="0.432642 0 0 0 0 0 0.432642 0 0 0 0 0 0.432642 0 0 0 0 0 1 0"
in="fbSourceGraphic" />
</filter>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient907"
id="linearGradient909"
x1="-1.6446429"
y1="8.0178574"
x2="17.555358"
y2="8.0178574"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.4"
inkscape:cx="-8.70357"
inkscape:cy="2.9092772"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1015"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<rect
style="fill:url(#linearGradient909);stroke:none;fill-opacity:1;opacity:1;filter:url(#filter1005)"
id="rect2985"
width="16"
height="16"
x="-0.044642858"
y="0.017857092"
transform="translate(0,1036.3622)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -14,8 +14,8 @@
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="list_icons.svg"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="meshvectors.svg"
inkscape:export-filename="/home/martin/lutra/qgis-crayfish-plugin/plugin/list_icons_d.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
@ -134,50 +134,58 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="2.8246129"
inkscape:cx="-2.6207406"
inkscape:cy="6.2123922"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="994"
inkscape:window-x="-4"
inkscape:window-y="-3"
inkscape:window-height="1015"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
showguides="true"
inkscape:guide-bbox="true">
<sodipodi:guide
orientation="1,0"
position="14.017857,5.8035714"
id="guide4180" />
id="guide4180"
inkscape:locked="false" />
<sodipodi:guide
orientation="0,1"
position="-3.5714286,1.9642857"
id="guide4182" />
id="guide4182"
inkscape:locked="false" />
<sodipodi:guide
orientation="1,0"
position="12.053571,10.982143"
id="guide4186" />
id="guide4186"
inkscape:locked="false" />
<sodipodi:guide
orientation="0,1"
position="-9.1964286,3.9732143"
id="guide4188" />
id="guide4188"
inkscape:locked="false" />
<sodipodi:guide
orientation="0,1"
position="-5.0446429,5.9821429"
id="guide4190" />
id="guide4190"
inkscape:locked="false" />
<sodipodi:guide
orientation="1,0"
position="10,8.3482143"
id="guide4192" />
id="guide4192"
inkscape:locked="false" />
<sodipodi:guide
orientation="1,0"
position="12.991071,10.714286"
id="guide4194" />
id="guide4194"
inkscape:locked="false" />
<sodipodi:guide
orientation="0,1"
position="8.9651038,2.9673231"
id="guide4196" />
id="guide4196"
inkscape:locked="false" />
</sodipodi:namedview>
<metadata
id="metadata7">
@ -187,7 +195,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@ -197,14 +205,15 @@
id="layer1"
transform="translate(0,-1036.3622)">
<path
style="fill:#b3b3b3;stroke:#b3b3b3;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-mid:none;marker-end:none"
d="m 2.5000001,1038.8622 10.9999999,11"
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-mid:none;marker-end:none;fill-opacity:0.23"
d="m 2.5000001,1038.8622 6.0050762,6.0051 4.9949237,4.9949"
id="path3789"
inkscape:connector-curvature="0"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
inkscape:export-ydpi="90"
sodipodi:nodetypes="ccc" />
<path
style="fill:#b3b3b3;fill-opacity:1;stroke:#b3b3b3;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 14.017857,1050.3979 12.991071,1046.3801 10,1049.3949 z"
id="path4184"
inkscape:connector-curvature="0"

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -0,0 +1,213 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="list_icons.svg"
inkscape:export-filename="/home/martin/lutra/qgis-crayfish-plugin/plugin/list_icons_d.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<marker
inkscape:stockid="TriangleOutM"
orient="auto"
refY="0.0"
refX="0.0"
id="TriangleOutM"
style="overflow:visible">
<path
id="path3940"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
transform="scale(0.4)" />
</marker>
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Send"
style="overflow:visible;">
<path
id="path3810"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mend"
style="overflow:visible;">
<path
id="path3804"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Lend"
style="overflow:visible;">
<path
id="path3816"
style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) rotate(180) translate(1,0)" />
</marker>
<marker
inkscape:stockid="TriangleOutL"
orient="auto"
refY="0.0"
refX="0.0"
id="TriangleOutL"
style="overflow:visible">
<path
id="path3937"
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
transform="scale(0.8)" />
</marker>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 8 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="16 : 8 : 1"
inkscape:persp3d-origin="8 : 5.3333333 : 1"
id="perspective3771" />
<linearGradient
id="linearGradient3755">
<stop
id="stop3767"
offset="0"
style="stop-color:#0000ff;stop-opacity:0.50196081;" />
<stop
id="stop3765"
offset="0.34999999"
style="stop-color:#00ffff;stop-opacity:0.50196081;" />
<stop
id="stop3763"
offset="0.5"
style="stop-color:#00ff00;stop-opacity:0.50196081;" />
<stop
style="stop-color:#ffff00;stop-opacity:0.50196081;"
offset="0.64999998"
id="stop3769" />
<stop
style="stop-color:#ff0000;stop-opacity:0.50980395;"
offset="1"
id="stop3759" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3755"
id="linearGradient3761"
x1="-0.044642858"
y1="0.071428955"
x2="15.955357"
y2="16.053572"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="2.8246129"
inkscape:cy="6.2123922"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="994"
inkscape:window-x="-4"
inkscape:window-y="-3"
inkscape:window-maximized="1"
showguides="true"
inkscape:guide-bbox="true">
<sodipodi:guide
orientation="1,0"
position="14.017857,5.8035714"
id="guide4180" />
<sodipodi:guide
orientation="0,1"
position="-3.5714286,1.9642857"
id="guide4182" />
<sodipodi:guide
orientation="1,0"
position="12.053571,10.982143"
id="guide4186" />
<sodipodi:guide
orientation="0,1"
position="-9.1964286,3.9732143"
id="guide4188" />
<sodipodi:guide
orientation="0,1"
position="-5.0446429,5.9821429"
id="guide4190" />
<sodipodi:guide
orientation="1,0"
position="10,8.3482143"
id="guide4192" />
<sodipodi:guide
orientation="1,0"
position="12.991071,10.714286"
id="guide4194" />
<sodipodi:guide
orientation="0,1"
position="8.9651038,2.9673231"
id="guide4196" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<path
style="fill:#b3b3b3;stroke:#b3b3b3;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-mid:none;marker-end:none"
d="m 2.5000001,1038.8622 10.9999999,11"
id="path3789"
inkscape:connector-curvature="0"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
<path
style="fill:#b3b3b3;fill-opacity:1;stroke:#b3b3b3;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 14.017857,1050.3979 12.991071,1046.3801 10,1049.3949 z"
id="path4184"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -45,6 +45,7 @@ Returns a dataset index within group()
Returns whether index is valid, ie at least groups is set
%End
bool operator == ( const QgsMeshDatasetIndex &other ) const;
bool operator != ( const QgsMeshDatasetIndex &other ) const;
};
typedef QgsPoint QgsMeshVertex;

View File

@ -20,15 +20,21 @@
#include <QList>
#include <QItemSelectionModel>
#include <QMouseEvent>
QgsMeshDatasetGroupTreeItem::QgsMeshDatasetGroupTreeItem( QgsMeshDatasetGroupTreeItem *parent )
: mParent( parent )
{
}
QgsMeshDatasetGroupTreeItem::QgsMeshDatasetGroupTreeItem( const QString &name, QgsMeshDatasetGroupTreeItem *parent )
QgsMeshDatasetGroupTreeItem::QgsMeshDatasetGroupTreeItem( const QString &name,
bool isVector,
int index,
QgsMeshDatasetGroupTreeItem *parent )
: mParent( parent )
, mName( name )
, mIsVector( isVector )
, mDatasetGroupIndex( index )
{
}
@ -50,11 +56,6 @@ QgsMeshDatasetGroupTreeItem *QgsMeshDatasetGroupTreeItem::child( int row ) const
return nullptr;
}
int QgsMeshDatasetGroupTreeItem::columnCount() const
{
return 1;
}
int QgsMeshDatasetGroupTreeItem::childCount() const
{
return mChildren.count();
@ -73,12 +74,22 @@ int QgsMeshDatasetGroupTreeItem::row() const
return 0;
}
QVariant QgsMeshDatasetGroupTreeItem::data( int column ) const
QString QgsMeshDatasetGroupTreeItem::name() const
{
Q_UNUSED( column );
return mName;
}
bool QgsMeshDatasetGroupTreeItem::isVector() const
{
return mIsVector;
}
int QgsMeshDatasetGroupTreeItem::datasetGroupIndex() const
{
return mDatasetGroupIndex;
}
/////////////////////////////////////////////////////////////////////////////////////////
QgsMeshDatasetGroupTreeModel::QgsMeshDatasetGroupTreeModel( QObject *parent )
@ -89,10 +100,60 @@ QgsMeshDatasetGroupTreeModel::QgsMeshDatasetGroupTreeModel( QObject *parent )
int QgsMeshDatasetGroupTreeModel::columnCount( const QModelIndex &parent ) const
{
if ( parent.isValid() )
return static_cast<QgsMeshDatasetGroupTreeItem *>( parent.internalPointer() )->columnCount();
else
return mRootItem->columnCount();
Q_UNUSED( parent );
return 1;
}
int QgsMeshDatasetGroupTreeModel::activeScalarGroup() const
{
return mActiveScalarGroupIndex;
}
void QgsMeshDatasetGroupTreeModel::setActiveScalarGroup( int group )
{
if ( mActiveScalarGroupIndex == group )
return;
int oldGroupIndex = mActiveScalarGroupIndex;
mActiveScalarGroupIndex = group;
if ( oldGroupIndex > -1 )
{
const auto index = groupIndexToModelIndex( oldGroupIndex );
emit dataChanged( index, index );
}
if ( group > -1 )
{
const auto index = groupIndexToModelIndex( group );
emit dataChanged( index, index );
}
}
int QgsMeshDatasetGroupTreeModel::activeVectorGroup() const
{
return mActiveVectorGroupIndex;
}
void QgsMeshDatasetGroupTreeModel::setActiveVectorGroup( int group )
{
if ( mActiveVectorGroupIndex == group )
return;
int oldGroupIndex = mActiveVectorGroupIndex;
mActiveVectorGroupIndex = group;
if ( oldGroupIndex > -1 )
{
const auto index = groupIndexToModelIndex( oldGroupIndex );
emit dataChanged( index, index );
}
if ( group > -1 )
{
const auto index = groupIndexToModelIndex( group );
emit dataChanged( index, index );
}
}
QVariant QgsMeshDatasetGroupTreeModel::data( const QModelIndex &index, int role ) const
@ -100,12 +161,24 @@ QVariant QgsMeshDatasetGroupTreeModel::data( const QModelIndex &index, int role
if ( !index.isValid() )
return QVariant();
if ( role != Qt::DisplayRole )
return QVariant();
QgsMeshDatasetGroupTreeItem *item = static_cast<QgsMeshDatasetGroupTreeItem *>( index.internalPointer() );
return item->data( index.column() );
switch ( role )
{
case Qt::DisplayRole:
case Name:
return item->name();
case IsVector:
return item->isVector();
case IsActiveScalarDatasetGroup:
return item->datasetGroupIndex() == mActiveScalarGroupIndex;
case IsActiveVectorDatasetGroup:
return item->datasetGroupIndex() == mActiveVectorGroupIndex;
case DatasetGroupIndex:
return item->datasetGroupIndex();
}
return QVariant();
}
Qt::ItemFlags QgsMeshDatasetGroupTreeModel::flags( const QModelIndex &index ) const
@ -113,7 +186,7 @@ Qt::ItemFlags QgsMeshDatasetGroupTreeModel::flags( const QModelIndex &index ) co
if ( !index.isValid() )
return Qt::NoItemFlags;
return QAbstractItemModel::flags( index );
return Qt::ItemIsEnabled;
}
QVariant QgsMeshDatasetGroupTreeModel::headerData( int section,
@ -176,34 +249,138 @@ int QgsMeshDatasetGroupTreeModel::rowCount( const QModelIndex &parent ) const
return parentItem->childCount();
}
void QgsMeshDatasetGroupTreeModel::setupModelData( const QStringList &groups )
void QgsMeshDatasetGroupTreeModel::syncToLayer( QgsMeshLayer *layer )
{
beginResetModel();
mRootItem.reset( new QgsMeshDatasetGroupTreeItem() );
mNameToItem.clear();
mDatasetGroupIndexToItem.clear();
for ( const QString &groupName : groups )
if ( layer && layer->dataProvider() )
{
QgsMeshDatasetGroupTreeItem *item = new QgsMeshDatasetGroupTreeItem( groupName, mRootItem.get() );
mRootItem->appendChild( item );
const QgsMeshDataProvider *dp = layer->dataProvider();
for ( int groupIndex = 0; groupIndex < dp->datasetGroupCount(); ++groupIndex )
{
const QgsMeshDatasetGroupMetadata meta = dp->datasetGroupMetadata( groupIndex );
const QString name = meta.name();
const bool isVector = meta.isVector();
const QStringList subdatasets = name.split( '/' );
if ( subdatasets.size() == 1 )
{
addTreeItem( name, isVector, groupIndex, mRootItem.get() );
}
else if ( subdatasets.size() == 2 )
{
auto i = mNameToItem.find( subdatasets[0] );
if ( i == mNameToItem.end() )
{
QgsDebugMsg( QStringLiteral( "Unable to find parent group for %1." ).arg( name ) );
addTreeItem( name, isVector, groupIndex, mRootItem.get() );
}
else
{
addTreeItem( subdatasets[1], isVector, groupIndex, i.value() );
}
}
else
{
QgsDebugMsg( QStringLiteral( "Ignoring too deep child group name %1." ).arg( name ) );
addTreeItem( name, isVector, groupIndex, mRootItem.get() );
}
}
}
endResetModel();
}
void QgsMeshDatasetGroupTreeModel::addTreeItem( const QString &groupName, bool isVector, int groupIndex, QgsMeshDatasetGroupTreeItem *parent )
{
Q_ASSERT( parent );
QgsMeshDatasetGroupTreeItem *item = new QgsMeshDatasetGroupTreeItem( groupName, isVector, groupIndex, parent );
parent->appendChild( item );
if ( mNameToItem.contains( groupName ) )
QgsDebugMsg( QStringLiteral( "Group %1 is not unique" ).arg( groupName ) );
mNameToItem[groupName] = item;
if ( mDatasetGroupIndexToItem.contains( groupIndex ) )
QgsDebugMsg( QStringLiteral( "Group index %1 is not unique" ).arg( groupIndex ) );
mDatasetGroupIndexToItem[groupIndex] = item;
}
QModelIndex QgsMeshDatasetGroupTreeModel::groupIndexToModelIndex( int groupIndex )
{
if ( groupIndex < 0 )
return QModelIndex();
const auto item = mDatasetGroupIndexToItem[groupIndex];
auto parentItem = item->parentItem();
if ( parentItem )
{
const auto parentIndex = index( parentItem->row(), 0, QModelIndex() );
return index( item->row(), 0, parentIndex );
}
else
return QModelIndex();
}
/////////////////////////////////////////////////////////////////////////////////////////
QgsMeshDatasetGroupTreeItemDelagate::QgsMeshDatasetGroupTreeItemDelagate( QObject *parent )
: QStyledItemDelegate( parent )
, mScalarSelectedPixmap( QStringLiteral( ":/images/themes/default/propertyicons/meshcontours.svg" ) )
, mScalarUnselectedPixmap( QStringLiteral( ":/images/themes/default/propertyicons/meshcontoursoff.svg" ) )
, mVectorSelectedPixmap( QStringLiteral( ":/images/themes/default/propertyicons/meshvectors.svg" ) )
, mVectorUnselectedPixmap( QStringLiteral( ":/images/themes/default/propertyicons/meshvectorsoff.svg" ) )
{
}
void QgsMeshDatasetGroupTreeItemDelagate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
if ( !painter )
return;
QStyledItemDelegate::paint( painter, option, index );
bool isVector = index.data( QgsMeshDatasetGroupTreeModel::IsVector ).toBool();
if ( isVector )
{
bool isActive = index.data( QgsMeshDatasetGroupTreeModel::IsActiveVectorDatasetGroup ).toBool();
painter->drawPixmap( iconRect( option.rect, true ), isActive ? mVectorSelectedPixmap : mVectorUnselectedPixmap );
}
bool isActive = index.data( QgsMeshDatasetGroupTreeModel::IsActiveScalarDatasetGroup ).toBool();
painter->drawPixmap( iconRect( option.rect, false ), isActive ? mScalarSelectedPixmap : mScalarUnselectedPixmap );
}
QRect QgsMeshDatasetGroupTreeItemDelagate::iconRect( const QRect rect, bool isVector ) const
{
int iw = mScalarSelectedPixmap.width();
int ih = mScalarSelectedPixmap.height();
int margin = ( rect.height() - ih ) / 2;
int i = isVector ? 1 : 2;
return QRect( rect.right() - i * ( iw + margin ), rect.top() + margin, iw, ih );
}
QSize QgsMeshDatasetGroupTreeItemDelagate::sizeHint( const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
QSize hint = QStyledItemDelegate::sizeHint( option, index );
if ( hint.height() < 16 )
hint.setHeight( 16 );
return hint;
}
/////////////////////////////////////////////////////////////////////////////////////////
QgsMeshDatasetGroupTreeView::QgsMeshDatasetGroupTreeView( QWidget *parent )
: QTreeView( parent )
{
setModel( &mModel );
setSelectionMode( QAbstractItemView::SingleSelection ) ;
connect( selectionModel(),
&QItemSelectionModel::selectionChanged,
this,
&QgsMeshDatasetGroupTreeView::onSelectionChanged
);
setItemDelegate( &mDelegate );
setSelectionMode( QAbstractItemView::SingleSelection );
}
void QgsMeshDatasetGroupTreeView::setLayer( QgsMeshLayer *layer )
@ -215,80 +392,84 @@ void QgsMeshDatasetGroupTreeView::setLayer( QgsMeshLayer *layer )
}
}
int QgsMeshDatasetGroupTreeView::activeGroup() const
int QgsMeshDatasetGroupTreeView::activeScalarGroup() const
{
return mActiveGroup;
return mModel.activeScalarGroup();
}
void QgsMeshDatasetGroupTreeView::onSelectionChanged( const QItemSelection &selected, const QItemSelection &deselected )
void QgsMeshDatasetGroupTreeView::setActiveScalarGroup( int group )
{
Q_UNUSED( deselected );
int group = -1;
if ( !selected.isEmpty() && !selected.first().indexes().isEmpty() )
if ( mModel.activeScalarGroup() != group )
{
QModelIndex index = selected.first().indexes().first(); //single selection only
group = index.row();
}
if ( mActiveGroup != group )
{
mActiveGroup = group;
emit activeGroupChanged();
mModel.setActiveScalarGroup( group );
emit activeScalarGroupChanged( group );
}
}
void QgsMeshDatasetGroupTreeView::extractGroups()
int QgsMeshDatasetGroupTreeView::activeVectorGroup() const
{
mGroups.clear();
return mModel.activeVectorGroup();
}
if ( !mMeshLayer || !mMeshLayer->dataProvider() )
return;
for ( int i = 0; i < mMeshLayer->dataProvider()->datasetGroupCount(); ++i )
void QgsMeshDatasetGroupTreeView::setActiveVectorGroup( int group )
{
if ( mModel.activeVectorGroup() != group )
{
const QgsMeshDatasetGroupMetadata meta = mMeshLayer->dataProvider()->datasetGroupMetadata( i );
mGroups << meta.name();
mModel.setActiveVectorGroup( group );
emit activeVectorGroupChanged( group );
}
}
void QgsMeshDatasetGroupTreeView::syncToLayer()
{
extractGroups();
mModel.setupModelData( mGroups );
int index = setActiveGroupFromActiveDataset();
if ( mGroups.size() > index )
setCurrentIndex( mModel.index( index, 0 ) );
mModel.syncToLayer( mMeshLayer );
setActiveGroupFromActiveDataset();
}
int QgsMeshDatasetGroupTreeView::setActiveGroupFromActiveDataset()
void QgsMeshDatasetGroupTreeView::mousePressEvent( QMouseEvent *event )
{
int group = -1;
if ( !event )
return;
bool processed = false;
const QModelIndex idx = indexAt( event->pos() );
if ( idx.isValid() )
{
const QRect vr = visualRect( idx );
if ( mDelegate.iconRect( vr, true ).contains( event->pos() ) )
{
bool isVector = idx.data( QgsMeshDatasetGroupTreeModel::IsVector ).toBool();
if ( isVector )
{
setActiveVectorGroup( idx.data( QgsMeshDatasetGroupTreeModel::DatasetGroupIndex ).toInt() );
processed = true;
}
}
else if ( mDelegate.iconRect( vr, false ).contains( event->pos() ) )
{
setActiveScalarGroup( idx.data( QgsMeshDatasetGroupTreeModel::DatasetGroupIndex ).toInt() );
processed = true;
}
}
// only if the user did not click one of the icons do usual handling
if ( !processed )
QTreeView::mousePressEvent( event );
}
void QgsMeshDatasetGroupTreeView::setActiveGroupFromActiveDataset()
{
int scalarGroup = -1;
int vectorGroup = -1;
// find active dataset
QgsMeshDatasetIndex activeDataset;
if ( mMeshLayer )
{
const QgsMeshRendererSettings rendererSettings = mMeshLayer->rendererSettings();
activeDataset = rendererSettings.activeScalarDataset();
if ( !activeDataset.isValid() )
activeDataset = rendererSettings.activeVectorDataset();
scalarGroup = rendererSettings.activeScalarDataset().group();
vectorGroup = rendererSettings.activeVectorDataset().group();
}
// find group that contains active dataset
if ( activeDataset.isValid() && activeDataset.group() < mGroups.size() )
{
group = activeDataset.group();
}
if ( mActiveGroup != group )
{
mActiveGroup = group;
emit activeGroupChanged();
}
return mActiveGroup;
setActiveScalarGroup( scalarGroup );
setActiveVectorGroup( vectorGroup );
}

View File

@ -24,6 +24,7 @@
#include <QVector>
#include <QItemSelection>
#include <QStandardItemModel>
#include <QStyledItemDelegate>
#include <QList>
#include <memory>
@ -39,25 +40,29 @@ class QgsMeshLayer;
*
* Groups:
* Depth
* - Maximum/Depth
* - Maximum
* Velocity
* Wind speed
* - Maximum/Wind Speed
* - Maximum
*/
class APP_NO_EXPORT QgsMeshDatasetGroupTreeItem
{
public:
QgsMeshDatasetGroupTreeItem( QgsMeshDatasetGroupTreeItem *parent = nullptr );
QgsMeshDatasetGroupTreeItem( const QString &name, QgsMeshDatasetGroupTreeItem *parent = nullptr );
QgsMeshDatasetGroupTreeItem( const QString &name,
bool isVector,
int index,
QgsMeshDatasetGroupTreeItem *parent = nullptr );
~QgsMeshDatasetGroupTreeItem();
void appendChild( QgsMeshDatasetGroupTreeItem *node );
QgsMeshDatasetGroupTreeItem *child( int row ) const;
int columnCount() const;
int childCount() const;
QgsMeshDatasetGroupTreeItem *parentItem() const;
int row() const;
QVariant data( int column ) const;
QString name() const;
bool isVector() const;
int datasetGroupIndex() const;
private:
QgsMeshDatasetGroupTreeItem *mParent = nullptr;
@ -65,6 +70,8 @@ class APP_NO_EXPORT QgsMeshDatasetGroupTreeItem
// Data
QString mName;
bool mIsVector = false;
int mDatasetGroupIndex = -1;
};
/**
@ -73,8 +80,16 @@ class APP_NO_EXPORT QgsMeshDatasetGroupTreeItem
class APP_NO_EXPORT QgsMeshDatasetGroupTreeModel : public QAbstractItemModel
{
Q_OBJECT
public:
enum Roles
{
Name = Qt::UserRole,
IsVector,
IsActiveScalarDatasetGroup,
IsActiveVectorDatasetGroup,
DatasetGroupIndex
};
explicit QgsMeshDatasetGroupTreeModel( QObject *parent = nullptr );
QVariant data( const QModelIndex &index, int role ) const override;
@ -87,11 +102,54 @@ class APP_NO_EXPORT QgsMeshDatasetGroupTreeModel : public QAbstractItemModel
int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
int columnCount( const QModelIndex &parent = QModelIndex() ) const override;
//! Add groups to the model
void setupModelData( const QStringList &groups );
//! Returns index of active group for contours
int activeScalarGroup() const;
//! Sets active group for contours
void setActiveScalarGroup( int group );
//! Returns index of active group for vectors
int activeVectorGroup() const;
//! Sets active vector group
void setActiveVectorGroup( int group );
//! Add groups to the model from mesh layer
void syncToLayer( QgsMeshLayer *layer );
private:
void addTreeItem( const QString &groupName, bool isVector, int groupIndex, QgsMeshDatasetGroupTreeItem *parent );
QModelIndex groupIndexToModelIndex( int groupIndex );
std::unique_ptr<QgsMeshDatasetGroupTreeItem> mRootItem;
QMap<QString, QgsMeshDatasetGroupTreeItem *> mNameToItem;
QMap<int, QgsMeshDatasetGroupTreeItem *> mDatasetGroupIndexToItem;
int mActiveScalarGroupIndex = -1;
int mActiveVectorGroupIndex = -1;
};
/**
* Delegate to display tree item with a contours and vector selector
*/
class APP_EXPORT QgsMeshDatasetGroupTreeItemDelagate: public QStyledItemDelegate
{
public:
QgsMeshDatasetGroupTreeItemDelagate( QObject *parent = Q_NULLPTR );
void paint( QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index ) const override;
//! Icon rectangle for given item rectangle
QRect iconRect( const QRect rect, bool isVector ) const;
QSize sizeHint( const QStyleOptionViewItem &option,
const QModelIndex &index ) const override;
private:
const QPixmap mScalarSelectedPixmap;
const QPixmap mScalarUnselectedPixmap;
const QPixmap mVectorSelectedPixmap;
const QPixmap mVectorUnselectedPixmap;
};
/**
@ -109,27 +167,39 @@ class APP_EXPORT QgsMeshDatasetGroupTreeView : public QTreeView
//! Associates mesh layer with the widget
void setLayer( QgsMeshLayer *layer );
//! Returns index of active group
int activeGroup() const;
//! Returns index of active group for contours
int activeScalarGroup() const;
//! Sets active group for contours
void setActiveScalarGroup( int group );
//! Returns index of active group for vectors
int activeVectorGroup() const;
//! Sets active vector group
void setActiveVectorGroup( int group );
//! Synchronize widgets state with associated mesh layer
void syncToLayer();
void mousePressEvent( QMouseEvent *event ) override;
signals:
//! Selected dataset group changed
void activeGroupChanged();
//! Selected dataset group for contours changed. -1 for invalid group
void activeScalarGroupChanged( int groupIndex );
//! Selected dataset group for vectors changed. -1 for invalid group
void activeVectorGroupChanged( int groupIndex );
private slots:
void onSelectionChanged( const QItemSelection &selected, const QItemSelection &deselected );
// void onSelectionChanged( const QItemSelection &selected, const QItemSelection &deselected );
private:
void extractGroups();
int setActiveGroupFromActiveDataset();
void setActiveGroupFromActiveDataset();
QgsMeshDatasetGroupTreeModel mModel;
QgsMeshDatasetGroupTreeItemDelagate mDelegate;
QgsMeshLayer *mMeshLayer = nullptr; // not owned
QStringList mGroups; // group names
int mActiveGroup = -1; // index of active group
};
#endif // QGSMESHDATASETGROUPTREE_H

View File

@ -24,7 +24,10 @@ QgsMeshRendererActiveDatasetWidget::QgsMeshRendererActiveDatasetWidget( QWidget
: QWidget( parent )
{
setupUi( this );
connect( mDatasetGroupTreeView, &QgsMeshDatasetGroupTreeView::activeGroupChanged, this, &QgsMeshRendererActiveDatasetWidget::onActiveGroupChanged );
connect( mDatasetGroupTreeView, &QgsMeshDatasetGroupTreeView::activeScalarGroupChanged,
this, &QgsMeshRendererActiveDatasetWidget::onActiveScalarGroupChanged );
connect( mDatasetGroupTreeView, &QgsMeshDatasetGroupTreeView::activeVectorGroupChanged,
this, &QgsMeshRendererActiveDatasetWidget::onActiveVectorGroupChanged );
connect( mDatasetSlider, &QSlider::valueChanged, this, &QgsMeshRendererActiveDatasetWidget::onActiveDatasetChanged );
}
@ -34,6 +37,16 @@ void QgsMeshRendererActiveDatasetWidget::setLayer( QgsMeshLayer *layer )
mDatasetGroupTreeView->setLayer( layer );
}
int QgsMeshRendererActiveDatasetWidget::activeScalarDatasetGroup() const
{
return mActiveScalarDatasetGroup;
}
int QgsMeshRendererActiveDatasetWidget::activeVectorDatasetGroup() const
{
return mActiveVectorDatasetGroup;
}
QgsMeshDatasetIndex QgsMeshRendererActiveDatasetWidget::activeScalarDataset() const
{
return mActiveScalarDataset;
@ -47,112 +60,162 @@ QgsMeshDatasetIndex QgsMeshRendererActiveDatasetWidget::activeVectorDataset() co
void QgsMeshRendererActiveDatasetWidget::setSliderRange()
{
int datasetCount = 1;
if ( mMeshLayer &&
mMeshLayer->dataProvider() &&
mDatasetGroupTreeView->activeGroup() != -1 )
datasetCount = mMeshLayer->dataProvider()->datasetCount( mDatasetGroupTreeView->activeGroup() );
if ( mMeshLayer && mMeshLayer->dataProvider() )
{
for ( int i = 0; i < mMeshLayer->dataProvider()->datasetGroupCount(); ++i )
{
datasetCount = std::max( mMeshLayer->dataProvider()->datasetCount( i ), datasetCount );
}
}
mDatasetSlider->setMinimum( 0 );
mDatasetSlider->setMaximum( datasetCount - 1 );
}
void QgsMeshRendererActiveDatasetWidget::onActiveGroupChanged()
void QgsMeshRendererActiveDatasetWidget::onActiveScalarGroupChanged( int groupIndex )
{
setSliderRange();
if ( groupIndex == mActiveScalarDatasetGroup )
return;
mActiveScalarDatasetGroup = groupIndex;
// keep the same timestep if possible
int val = mDatasetSlider->value();
if ( ( val < 0 ) || ( val > mDatasetSlider->maximum() ) )
val = 0;
onActiveDatasetChanged( val );
emit activeScalarGroupChanged( mActiveScalarDatasetGroup );
}
void QgsMeshRendererActiveDatasetWidget::onActiveVectorGroupChanged( int groupIndex )
{
if ( groupIndex == mActiveVectorDatasetGroup )
return;
mActiveVectorDatasetGroup = groupIndex;
// keep the same timestep if possible
int val = mDatasetSlider->value();
mDatasetSlider->setValue( val );
onActiveDatasetChanged( val );
mActiveDatasetGroup = mDatasetGroupTreeView->activeGroup();
emit activeDatasetGroupChanged( mActiveDatasetGroup );
emit activeVectorGroupChanged( mActiveVectorDatasetGroup );
}
void QgsMeshRendererActiveDatasetWidget::onActiveDatasetChanged( int value )
{
int groupIndex = mDatasetGroupTreeView->activeGroup();
if ( !mMeshLayer || !mMeshLayer->dataProvider() )
return;
mActiveScalarDataset = QgsMeshDatasetIndex();
mActiveVectorDataset = QgsMeshDatasetIndex();
QgsMeshDatasetIndex datasetIndex( groupIndex, value );
bool changed = false;
if ( mMeshLayer &&
mMeshLayer->dataProvider() &&
datasetIndex.isValid() &&
mMeshLayer->dataProvider()->datasetCount( groupIndex ) > value )
QgsMeshDatasetIndex activeScalarDataset(
mActiveScalarDatasetGroup,
std::min( value, mMeshLayer->dataProvider()->datasetCount( mActiveScalarDatasetGroup ) - 1 )
);
if ( activeScalarDataset != mActiveScalarDataset )
{
const QgsMeshDatasetGroupMetadata meta = mMeshLayer->dataProvider()->datasetGroupMetadata( datasetIndex );
mActiveScalarDataset = datasetIndex;
if ( meta.isVector() )
mActiveVectorDataset = datasetIndex;
mActiveScalarDataset = activeScalarDataset;
changed = true;
emit activeScalarDatasetChanged( mActiveScalarDataset );
}
updateMetadata( datasetIndex );
QgsMeshDatasetIndex activeVectorDataset(
mActiveVectorDatasetGroup,
std::min( value, mMeshLayer->dataProvider()->datasetCount( mActiveVectorDatasetGroup ) - 1 )
);
if ( activeVectorDataset != mActiveVectorDataset )
{
mActiveVectorDataset = activeVectorDataset;
changed = true;
emit activeVectorDatasetChanged( mActiveVectorDataset );
}
emit activeScalarDatasetChanged( activeScalarDataset() );
emit activeVectorDatasetChanged( activeVectorDataset() );
emit widgetChanged();
if ( changed )
{
updateMetadata();
emit widgetChanged();
}
}
void QgsMeshRendererActiveDatasetWidget::updateMetadata( QgsMeshDatasetIndex datasetIndex )
void QgsMeshRendererActiveDatasetWidget::updateMetadata()
{
QString msg;
if ( !mMeshLayer ||
!mMeshLayer->dataProvider() ||
!datasetIndex.isValid() )
!mMeshLayer->dataProvider() )
{
mActiveDatasetMetadata->setText( tr( "No dataset selected" ) );
msg += tr( "Invalid mesh layer selected" );
}
else
{
QString msg;
msg += QStringLiteral( "<table>" );
const QgsMeshDatasetMetadata meta = mMeshLayer->dataProvider()->datasetMetadata( datasetIndex );
msg += QStringLiteral( "<tr><td>%1</td><td>%2</td></tr>" )
.arg( tr( "Is valid" ) )
.arg( meta.isValid() ? tr( "Yes" ) : tr( "No" ) );
msg += QStringLiteral( "<tr><td>%1</td><td>%2</td></tr>" )
.arg( tr( "Time" ) )
.arg( meta.time() );
const QgsMeshDatasetGroupMetadata gmeta = mMeshLayer->dataProvider()->datasetGroupMetadata( datasetIndex );
msg += QStringLiteral( "<tr><td>%1</td><td>%2</td></tr>" )
.arg( tr( "Data Type" ) )
.arg( gmeta.dataType() == QgsMeshDatasetGroupMetadata::DataOnVertices ? tr( "Defined on vertices" ) : tr( "Defined on faces" ) );
msg += QStringLiteral( "<tr><td>%1</td><td>%2</td></tr>" )
.arg( tr( "Is vector" ) )
.arg( gmeta.isVector() ? tr( "Yes" ) : tr( "No" ) );
for ( auto it = gmeta.extraOptions().constBegin(); it != gmeta.extraOptions().constEnd(); ++it )
if ( mActiveScalarDataset.isValid() )
{
msg += QStringLiteral( "<tr><td>%1</td><td>%2</td></tr>" ).arg( it.key() ).arg( it.value() );
if ( mActiveVectorDataset.isValid() )
{
if ( mActiveScalarDataset == mActiveVectorDataset )
{
msg += metadata( mActiveScalarDataset );
}
else
{
msg += QStringLiteral( "<p> <h3> %1 </h3> " ).arg( tr( "Scalar dataset" ) );
msg += metadata( mActiveScalarDataset );
msg += QStringLiteral( "</p> <p> <h3> %1 </h3>" ).arg( tr( "Vector dataset" ) );
msg += metadata( mActiveVectorDataset );
msg += QStringLiteral( "</p>" );
}
}
else
{
msg += metadata( mActiveScalarDataset );
}
}
else
{
if ( mActiveVectorDataset.isValid() )
{
msg += metadata( mActiveVectorDataset );
}
else
{
msg += tr( "No mesh dataset selected" );
}
}
msg += QStringLiteral( "</table>" );
mActiveDatasetMetadata->setText( msg );
}
mActiveDatasetMetadata->setText( msg );
}
QgsMeshDatasetIndex QgsMeshRendererActiveDatasetWidget::datasetIndex() const
{
int value = mDatasetSlider->value();
int groupIndex = mDatasetGroupTreeView->activeGroup();
if ( mMeshLayer &&
mMeshLayer->dataProvider() &&
groupIndex != -1 &&
mMeshLayer->dataProvider()->datasetCount( groupIndex ) > value
)
return QgsMeshDatasetIndex( groupIndex, value );
else
return QgsMeshDatasetIndex();
QString QgsMeshRendererActiveDatasetWidget::metadata( QgsMeshDatasetIndex datasetIndex )
{
QString msg;
msg += QStringLiteral( "<table>" );
const QgsMeshDatasetMetadata meta = mMeshLayer->dataProvider()->datasetMetadata( datasetIndex );
msg += QStringLiteral( "<tr><td>%1</td><td>%2</td></tr>" )
.arg( tr( "Is valid" ) )
.arg( meta.isValid() ? tr( "Yes" ) : tr( "No" ) );
msg += QStringLiteral( "<tr><td>%1</td><td>%2</td></tr>" )
.arg( tr( "Time" ) )
.arg( meta.time() );
const QgsMeshDatasetGroupMetadata gmeta = mMeshLayer->dataProvider()->datasetGroupMetadata( datasetIndex );
msg += QStringLiteral( "<tr><td>%1</td><td>%2</td></tr>" )
.arg( tr( "Data Type" ) )
.arg( gmeta.dataType() == QgsMeshDatasetGroupMetadata::DataOnVertices ? tr( "Defined on vertices" ) : tr( "Defined on faces" ) );
msg += QStringLiteral( "<tr><td>%1</td><td>%2</td></tr>" )
.arg( tr( "Is vector" ) )
.arg( gmeta.isVector() ? tr( "Yes" ) : tr( "No" ) );
for ( auto it = gmeta.extraOptions().constBegin(); it != gmeta.extraOptions().constEnd(); ++it )
{
msg += QStringLiteral( "<tr><td>%1</td><td>%2</td></tr>" ).arg( it.key() ).arg( it.value() );
}
msg += QStringLiteral( "</table>" );
return msg;
}
void QgsMeshRendererActiveDatasetWidget::syncToLayer()
@ -164,22 +227,26 @@ void QgsMeshRendererActiveDatasetWidget::syncToLayer()
if ( mMeshLayer )
{
const QgsMeshRendererSettings rendererSettings = mMeshLayer->rendererSettings();
mActiveDatasetGroup = mDatasetGroupTreeView->activeGroup();
mActiveScalarDatasetGroup = mDatasetGroupTreeView->activeScalarGroup();
mActiveVectorDatasetGroup = mDatasetGroupTreeView->activeVectorGroup();
mActiveScalarDataset = rendererSettings.activeScalarDataset();
mActiveVectorDataset = rendererSettings.activeVectorDataset();
}
else
{
mActiveDatasetGroup = -1;
mActiveScalarDatasetGroup = -1;
mActiveVectorDatasetGroup = -1;
mActiveScalarDataset = QgsMeshDatasetIndex();
mActiveVectorDataset = QgsMeshDatasetIndex();
}
setSliderRange();
int val = 0;
if ( mActiveScalarDataset.isValid() )
val = mActiveScalarDataset.dataset();
else if ( mActiveVectorDataset.isValid() )
val = mActiveVectorDataset.dataset();
mDatasetSlider->setValue( val );
setSliderRange();
onActiveDatasetChanged( val );
}

View File

@ -47,10 +47,10 @@ class APP_EXPORT QgsMeshRendererActiveDatasetWidget : public QWidget, private Ui
void setLayer( QgsMeshLayer *layer );
//! Returns index of the active scalar dataset group
int activeScalarDatasetGroup() const { return mActiveDatasetGroup; }
int activeScalarDatasetGroup() const;
//! Returns index of the active vector dataset group
int activeVectorDatasetGroup() const { return mActiveDatasetGroup; }
int activeVectorDatasetGroup() const;
//! Gets index of the selected/active scalar dataset
QgsMeshDatasetIndex activeScalarDataset() const;
@ -69,23 +69,29 @@ class APP_EXPORT QgsMeshRendererActiveDatasetWidget : public QWidget, private Ui
//! Emitted when active vector dataset changed
void activeVectorDatasetChanged( QgsMeshDatasetIndex index );
//! Emitted when the current group gets changed
void activeDatasetGroupChanged( int groupIndex );
//! Emitted when the current scalar group gets changed
void activeScalarGroupChanged( int groupIndex );
//! Emitted when the current vector group gets changed
void activeVectorGroupChanged( int groupIndex );
//! Emitted when any settings related to rendering changed
void widgetChanged();
private slots:
void onActiveGroupChanged();
void onActiveScalarGroupChanged( int groupIndex );
void onActiveVectorGroupChanged( int groupIndex );
void onActiveDatasetChanged( int value );
void updateMetadata( QgsMeshDatasetIndex datasetIndex );
void updateMetadata( );
QString metadata( QgsMeshDatasetIndex datasetIndex );
private:
QgsMeshDatasetIndex datasetIndex() const;
//! Loop through all dataset groups and find the maximum number of datasets
void setSliderRange();
QgsMeshLayer *mMeshLayer = nullptr; // not owned
int mActiveDatasetGroup = -1;
int mActiveScalarDatasetGroup = -1;
int mActiveVectorDatasetGroup = -1;
QgsMeshDatasetIndex mActiveScalarDataset;
QgsMeshDatasetIndex mActiveVectorDataset;
};

View File

@ -44,8 +44,10 @@ QgsRendererMeshPropertiesWidget::QgsRendererMeshPropertiesWidget( QgsMeshLayer *
mMeshRendererVectorSettingsWidget->setLayer( mMeshLayer );
syncToLayer();
connect( mMeshRendererActiveDatasetWidget, &QgsMeshRendererActiveDatasetWidget::activeDatasetGroupChanged,
this, &QgsRendererMeshPropertiesWidget::onActiveDatasetGroupChanged );
connect( mMeshRendererActiveDatasetWidget, &QgsMeshRendererActiveDatasetWidget::activeScalarGroupChanged,
this, &QgsRendererMeshPropertiesWidget::onActiveScalarGroupChanged );
connect( mMeshRendererActiveDatasetWidget, &QgsMeshRendererActiveDatasetWidget::activeVectorGroupChanged,
this, &QgsRendererMeshPropertiesWidget::onActiveVectorGroupChanged );
connect( mNativeMeshGroup, &QGroupBox::toggled, this, &QgsPanelWidget::widgetChanged );
connect( mTriangularMeshGroup, &QGroupBox::toggled, this, &QgsPanelWidget::widgetChanged );
@ -108,24 +110,24 @@ void QgsRendererMeshPropertiesWidget::syncToLayer()
mNativeMeshSettingsWidget->syncToLayer();
mTriangularMeshSettingsWidget->syncToLayer();
onActiveDatasetGroupChanged();
onActiveScalarGroupChanged( mMeshRendererActiveDatasetWidget->activeScalarDatasetGroup() );
onActiveVectorGroupChanged( mMeshRendererActiveDatasetWidget->activeVectorDatasetGroup() );
}
void QgsRendererMeshPropertiesWidget::onActiveDatasetGroupChanged()
void QgsRendererMeshPropertiesWidget::onActiveScalarGroupChanged( int groupIndex )
{
int scalarGroup = mMeshRendererActiveDatasetWidget->activeScalarDatasetGroup();
int vectorGroup = mMeshRendererActiveDatasetWidget->activeVectorDatasetGroup();
if ( vectorGroup >= 0 && !mMeshLayer->dataProvider()->datasetGroupMetadata( vectorGroup ).isVector() )
vectorGroup = -1;
mMeshRendererScalarSettingsWidget->setActiveDatasetGroup( scalarGroup );
mMeshRendererVectorSettingsWidget->setActiveDatasetGroup( vectorGroup );
mMeshRendererScalarSettingsWidget->setActiveDatasetGroup( groupIndex );
mMeshRendererScalarSettingsWidget->syncToLayer();
mMeshRendererVectorSettingsWidget->syncToLayer();
mContoursGroupBox->setChecked( scalarGroup >= 0 );
mContoursGroupBox->setEnabled( scalarGroup >= 0 );
mVectorsGroupBox->setChecked( vectorGroup >= 0 );
mVectorsGroupBox->setEnabled( vectorGroup >= 0 );
mContoursGroupBox->setChecked( groupIndex >= 0 );
mContoursGroupBox->setEnabled( groupIndex >= 0 );
}
void QgsRendererMeshPropertiesWidget::onActiveVectorGroupChanged( int groupIndex )
{
if ( groupIndex >= 0 && !mMeshLayer->dataProvider()->datasetGroupMetadata( groupIndex ).isVector() )
groupIndex = -1;
mMeshRendererVectorSettingsWidget->setActiveDatasetGroup( groupIndex );
mMeshRendererVectorSettingsWidget->syncToLayer();
mVectorsGroupBox->setChecked( groupIndex >= 0 );
mVectorsGroupBox->setEnabled( groupIndex >= 0 );
}

View File

@ -53,7 +53,8 @@ class APP_EXPORT QgsRendererMeshPropertiesWidget : public QgsMapLayerConfigWidge
void syncToLayer();
private slots:
void onActiveDatasetGroupChanged();
void onActiveScalarGroupChanged( int groupIndex );
void onActiveVectorGroupChanged( int groupIndex );
private:
QgsMeshLayer *mMeshLayer = nullptr; //not owned

View File

@ -39,9 +39,16 @@ bool QgsMeshDatasetIndex::isValid() const
bool QgsMeshDatasetIndex::operator ==( const QgsMeshDatasetIndex &other ) const
{
return other.group() == group() && other.dataset() == dataset();
if ( isValid() && other.isValid() )
return other.group() == group() && other.dataset() == dataset();
else
return isValid() == other.isValid();
}
bool QgsMeshDatasetIndex::operator !=( const QgsMeshDatasetIndex &other ) const
{
return !( operator==( other ) );
}
QgsMeshDataProvider::QgsMeshDataProvider( const QString &uri, const QgsDataProvider::ProviderOptions &options )
: QgsDataProvider( uri, options )

View File

@ -51,6 +51,8 @@ class CORE_EXPORT QgsMeshDatasetIndex
bool isValid() const;
//! Equality operator
bool operator == ( const QgsMeshDatasetIndex &other ) const;
//! Inequality operator
bool operator != ( const QgsMeshDatasetIndex &other ) const;
private:
int mGroupIndex = -1;
int mDatasetIndex = -1;