Allow resolving errors

This commit is contained in:
Matthias Kuhn 2018-09-29 15:17:34 +02:00
parent dc2c78f328
commit 4607930ece
No known key found for this signature in database
GPG Key ID: 7A7F1A1C90C3E6A7
15 changed files with 200 additions and 18 deletions

View File

@ -31,6 +31,7 @@ It will be retrieved from the cache or from the underlying layer if unavailable.
If the feature is neither available from the cache nor from the layer it will return false. If the feature is neither available from the cache nor from the layer it will return false.
%End %End
virtual void updateFeature( QgsFeature &feature ) = 0; virtual void updateFeature( QgsFeature &feature ) = 0;
%Docstring %Docstring
Updates a feature in this pool. Updates a feature in this pool.

View File

@ -62,6 +62,23 @@ bool QgsFeaturePool::getFeature( QgsFeatureId id, QgsFeature &feature )
return true; return true;
} }
QgsFeatureIds QgsFeaturePool::getFeatures( const QgsFeatureRequest &request )
{
QgsFeatureIds fids;
std::unique_ptr<QgsVectorLayerFeatureSource> source = QgsVectorLayerUtils::getFeatureSource( mLayer );
QgsFeatureIterator it = source->getFeatures( request );
QgsFeature feature;
while ( it.nextFeature( feature ) )
{
insertFeature( feature );
fids << feature.id();
}
return fids;
}
QgsFeatureIds QgsFeaturePool::allFeatureIds() const QgsFeatureIds QgsFeaturePool::allFeatureIds() const
{ {
return mFeatureIds; return mFeatureIds;

View File

@ -46,6 +46,12 @@ class ANALYSIS_EXPORT QgsFeaturePool : public QgsFeatureSink SIP_ABSTRACT
*/ */
bool getFeature( QgsFeatureId id, QgsFeature &feature ); bool getFeature( QgsFeatureId id, QgsFeature &feature );
/**
* Warm the cache ...
* TODO write more docs
*/
QgsFeatureIds getFeatures( const QgsFeatureRequest &request ) SIP_SKIP;
/** /**
* Updates a feature in this pool. * Updates a feature in this pool.
* Implementations will update the feature on the layer or on the data provider. * Implementations will update the feature on the layer or on the data provider.

View File

@ -97,7 +97,7 @@ void QgsGeometryGapCheck::collectErrors( const QMap<QString, QgsFeaturePool *> &
} }
// Skip gaps above threshold // Skip gaps above threshold
if ( gapGeom->area() > mGapThresholdMapUnits || gapGeom->area() < mContext->reducedTolerance ) if ( ( mGapThresholdMapUnits > 0 && gapGeom->area() > mGapThresholdMapUnits ) || gapGeom->area() < mContext->reducedTolerance )
{ {
continue; continue;
} }

View File

@ -78,6 +78,12 @@ class ANALYSIS_EXPORT QgsGeometryGapCheck : public QgsGeometryCheck
public: public:
enum ResolutionMethod { MergeLongestEdge, NoChange }; enum ResolutionMethod { MergeLongestEdge, NoChange };
/**
* The \a configuration accepts a "gapThreshold" key which specifies
* the maximum gap size in squared map units. Any gaps which are larger
* than this area are accepted. If "gapThreshold" is set to 0, the check
* is disabled.
*/
explicit QgsGeometryGapCheck( const QgsGeometryCheckContext *context, const QVariantMap &configuration ); explicit QgsGeometryGapCheck( const QgsGeometryCheckContext *context, const QVariantMap &configuration );
QList<QgsWkbTypes::GeometryType> compatibleGeometryTypes() const override { return factoryCompatibleGeometryTypes(); } QList<QgsWkbTypes::GeometryType> compatibleGeometryTypes() const override { return factoryCompatibleGeometryTypes(); }

View File

@ -71,11 +71,32 @@ void QgsGeometryMissingVertexCheck::fixError( const QMap<QString, QgsFeaturePool
{ {
error->setFixed( method ); error->setFixed( method );
} }
if ( method == AddMissingVertex )
{
QgsFeaturePool *featurePool = featurePools[ error->layerId() ];
QgsFeature feature;
featurePool->getFeature( error->featureId(), feature );
QgsPointXY pointOnSegment; // Should be equal to location
int vertexIndex;
QgsGeometry geometry = feature.geometry();
geometry.closestSegmentWithContext( error->location(), pointOnSegment, vertexIndex );
geometry.insertVertex( QgsPoint( error->location() ), vertexIndex );
feature.setGeometry( geometry );
featurePool->updateFeature( feature );
// TODO update "changes" structure
error->setFixed( method );
}
} }
QStringList QgsGeometryMissingVertexCheck::resolutionMethods() const QStringList QgsGeometryMissingVertexCheck::resolutionMethods() const
{ {
static QStringList methods = QStringList() << tr( "No action" ); static QStringList methods = QStringList()
<< tr( "No action" )
<< tr( "Add missing vertex" );
return methods; return methods;
} }

View File

@ -37,7 +37,8 @@ class ANALYSIS_EXPORT QgsGeometryMissingVertexCheck : public QgsGeometryCheck
public: public:
enum ResolutionMethod enum ResolutionMethod
{ {
NoChange NoChange,
AddMissingVertex
}; };
explicit QgsGeometryMissingVertexCheck( const QgsGeometryCheckContext *context, const QVariantMap &geometryCheckConfiguration ); explicit QgsGeometryMissingVertexCheck( const QgsGeometryCheckContext *context, const QVariantMap &geometryCheckConfiguration );

View File

@ -939,6 +939,7 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
mGeometryValidationModel->setCurrentLayer( qobject_cast<QgsVectorLayer *>( layer ) ); mGeometryValidationModel->setCurrentLayer( qobject_cast<QgsVectorLayer *>( layer ) );
} ); } );
mGeometryValidationDock->setGeometryValidationModel( mGeometryValidationModel ); mGeometryValidationDock->setGeometryValidationModel( mGeometryValidationModel );
mGeometryValidationDock->setGeometryValidationService( mGeometryValidationService.get() );
addDockWidget( Qt::RightDockWidgetArea, mGeometryValidationDock ); addDockWidget( Qt::RightDockWidgetArea, mGeometryValidationDock );
endProfile(); endProfile();

View File

@ -15,7 +15,12 @@ email : matthias@opengis.ch
#include "qgsgeometryvalidationdock.h" #include "qgsgeometryvalidationdock.h"
#include "qgsgeometryvalidationmodel.h" #include "qgsgeometryvalidationmodel.h"
#include "qgsgeometryvalidationservice.h"
#include "qgsmapcanvas.h" #include "qgsmapcanvas.h"
#include "qgsrubberband.h"
#include "qgsvectorlayer.h"
#include "qgsgeometrycheck.h"
#include "qgsgeometrycheckerror.h"
#include <QButtonGroup> #include <QButtonGroup>
@ -32,8 +37,23 @@ QgsGeometryValidationDock::QgsGeometryValidationDock( const QString &title, QgsM
connect( mMapCanvas, &QgsMapCanvas::currentLayerChanged, this, &QgsGeometryValidationDock::updateLayerTransform ); connect( mMapCanvas, &QgsMapCanvas::currentLayerChanged, this, &QgsGeometryValidationDock::updateLayerTransform );
connect( mMapCanvas, &QgsMapCanvas::destinationCrsChanged, this, &QgsGeometryValidationDock::updateLayerTransform ); connect( mMapCanvas, &QgsMapCanvas::destinationCrsChanged, this, &QgsGeometryValidationDock::updateLayerTransform );
connect( mMapCanvas, &QgsMapCanvas::transformContextChanged, this, &QgsGeometryValidationDock::updateLayerTransform ); connect( mMapCanvas, &QgsMapCanvas::transformContextChanged, this, &QgsGeometryValidationDock::updateLayerTransform );
mFeatureRubberband = new QgsRubberBand( mMapCanvas );
mErrorRubberband = new QgsRubberBand( mMapCanvas );
mErrorLocationRubberband = new QgsRubberBand( mMapCanvas );
double scaleFactor = mMapCanvas->fontMetrics().xHeight() * .2;
mFeatureRubberband->setColor( QColor( 250, 180, 180, 100 ) );
mFeatureRubberband->setWidth( scaleFactor );
mErrorRubberband->setColor( QColor( 180, 250, 180, 100 ) );
mErrorRubberband->setWidth( scaleFactor );
mErrorLocationRubberband->setIcon( QgsRubberBand::ICON_X );
mErrorLocationRubberband->setWidth( scaleFactor * 3 );
mErrorLocationRubberband->setColor( QColor( 180, 180, 250, 100 ) );
} }
QgsGeometryValidationModel *QgsGeometryValidationDock::geometryValidationModel() const QgsGeometryValidationModel *QgsGeometryValidationDock::geometryValidationModel() const
{ {
return mGeometryValidationModel; return mGeometryValidationModel;
@ -89,6 +109,16 @@ void QgsGeometryValidationDock::updateLayerTransform()
mLayerTransform = QgsCoordinateTransform( mMapCanvas->currentLayer()->crs(), mMapCanvas->mapSettings().destinationCrs(), mMapCanvas->mapSettings().transformContext() ); mLayerTransform = QgsCoordinateTransform( mMapCanvas->currentLayer()->crs(), mMapCanvas->mapSettings().destinationCrs(), mMapCanvas->mapSettings().transformContext() );
} }
QgsGeometryValidationService *QgsGeometryValidationDock::geometryValidationService() const
{
return mGeometryValidationService;
}
void QgsGeometryValidationDock::setGeometryValidationService( QgsGeometryValidationService *geometryValidationService )
{
mGeometryValidationService = geometryValidationService;
}
QModelIndex QgsGeometryValidationDock::currentIndex() const QModelIndex QgsGeometryValidationDock::currentIndex() const
{ {
return mErrorListView->selectionModel()->currentIndex(); return mErrorListView->selectionModel()->currentIndex();
@ -102,6 +132,38 @@ void QgsGeometryValidationDock::onCurrentErrorChanged( const QModelIndex &curren
mProblemDetailWidget->setVisible( current.isValid() ); mProblemDetailWidget->setVisible( current.isValid() );
mProblemDescriptionLabel->setText( current.data().toString() ); mProblemDescriptionLabel->setText( current.data().toString() );
{
QgsGeometryCheckError *error = current.data( QgsGeometryValidationModel::GeometryCheckErrorRole ).value<QgsGeometryCheckError *>();
while ( QPushButton *btn = mResolutionWidget->findChild<QPushButton *>() )
delete btn;
const QStringList resolutionMethods = error->check()->resolutionMethods();
int resolutionIndex = 0;
for ( const QString &resolutionMethod : resolutionMethods )
{
QPushButton *resolveBtn = new QPushButton( resolutionMethod );
connect( resolveBtn, &QPushButton::clicked, this, [resolutionIndex, error, this]()
{
mGeometryValidationService->fixError( error, resolutionIndex );
} );
mResolutionWidget->layout()->addWidget( resolveBtn );
resolutionIndex++;
}
}
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mMapCanvas->currentLayer() );
if ( vlayer )
{
QgsGeometry featureGeometry = current.data( QgsGeometryValidationModel::FeatureGeometryRole ).value<QgsGeometry>();
QgsGeometry errorGeometry = current.data( QgsGeometryValidationModel::ErrorGeometryRole ).value<QgsGeometry>();
QgsPointXY locationGeometry = current.data( QgsGeometryValidationModel::ErrorLocationGeometryRole ).value<QgsPointXY>();
qDebug() << "feature geom : " << featureGeometry.asWkt();
qDebug() << "error geom : " << errorGeometry.asWkt();
qDebug() << "locationgeom : " << QgsGeometry( new QgsPoint( locationGeometry ) ).asWkt();
mFeatureRubberband->setToGeometry( featureGeometry );
mErrorRubberband->setToGeometry( errorGeometry );
mErrorLocationRubberband->setToGeometry( QgsGeometry( new QgsPoint( locationGeometry ) ) );
}
switch ( mLastZoomToAction ) switch ( mLastZoomToAction )
{ {

View File

@ -22,6 +22,8 @@ email : matthias@opengis.ch
class QgsMapCanvas; class QgsMapCanvas;
class QgsGeometryValidationModel; class QgsGeometryValidationModel;
class QgsGeometryValidationService;
class QgsRubberBand;
/** /**
* @brief The QgsGeometryValidationDock class * @brief The QgsGeometryValidationDock class
@ -36,6 +38,9 @@ class QgsGeometryValidationDock : public QgsDockWidget, public Ui_QgsGeometryVal
QgsGeometryValidationModel *geometryValidationModel() const; QgsGeometryValidationModel *geometryValidationModel() const;
void setGeometryValidationModel( QgsGeometryValidationModel *geometryValidationModel ); void setGeometryValidationModel( QgsGeometryValidationModel *geometryValidationModel );
QgsGeometryValidationService *geometryValidationService() const;
void setGeometryValidationService( QgsGeometryValidationService *geometryValidationService );
private slots: private slots:
void onCurrentErrorChanged( const QModelIndex &current, const QModelIndex &previous ); void onCurrentErrorChanged( const QModelIndex &current, const QModelIndex &previous );
void gotoNextError(); void gotoNextError();
@ -52,10 +57,14 @@ class QgsGeometryValidationDock : public QgsDockWidget, public Ui_QgsGeometryVal
}; };
ZoomToAction mLastZoomToAction = ZoomToFeature; ZoomToAction mLastZoomToAction = ZoomToFeature;
QgsGeometryValidationModel *mGeometryValidationModel = nullptr; QgsGeometryValidationModel *mGeometryValidationModel = nullptr;
QgsGeometryValidationService *mGeometryValidationService = nullptr;
QButtonGroup *mZoomToButtonGroup = nullptr; QButtonGroup *mZoomToButtonGroup = nullptr;
QgsMapCanvas *mMapCanvas = nullptr; QgsMapCanvas *mMapCanvas = nullptr;
QgsCoordinateTransform mLayerTransform; QgsCoordinateTransform mLayerTransform;
QModelIndex currentIndex() const; QModelIndex currentIndex() const;
QgsRubberBand *mFeatureRubberband = nullptr;
QgsRubberBand *mErrorRubberband = nullptr;
QgsRubberBand *mErrorLocationRubberband = nullptr;
}; };
#endif // QGSGEOMETRYVALIDATIONPANEL_H #endif // QGSGEOMETRYVALIDATIONPANEL_H

View File

@ -74,6 +74,28 @@ QVariant QgsGeometryValidationModel::data( const QModelIndex &index, int role )
{ {
return topologyError->affectedAreaBBox(); return topologyError->affectedAreaBBox();
} }
case ErrorGeometryRole:
{
return topologyError->geometry();
}
case FeatureGeometryRole:
{
const QgsFeatureId fid = topologyError->featureId();
const QgsFeature feature = mCurrentLayer->getFeature( fid ); // TODO: this should be cached!
return feature.geometry();
}
case ErrorLocationGeometryRole:
{
return topologyError->location();
}
case GeometryCheckErrorRole:
{
return QVariant::fromValue<QgsGeometryCheckError *>( topologyError.get() );
}
} }
} }
else else

View File

@ -16,7 +16,11 @@ class QgsGeometryValidationModel : public QAbstractItemModel
enum Roles enum Roles
{ {
FeatureExtentRole = Qt::UserRole, FeatureExtentRole = Qt::UserRole,
ProblemExtentRole ProblemExtentRole,
ErrorGeometryRole,
FeatureGeometryRole,
ErrorLocationGeometryRole,
GeometryCheckErrorRole
}; };
QgsGeometryValidationModel( QgsGeometryValidationService *geometryValidationService, QObject *parent = nullptr ); QgsGeometryValidationModel( QgsGeometryValidationService *geometryValidationService, QObject *parent = nullptr );

View File

@ -40,6 +40,13 @@ bool QgsGeometryValidationService::validationActive( QgsVectorLayer *layer, QgsF
return false; return false;
} }
void QgsGeometryValidationService::fixError( const QgsGeometryCheckError *error, int method )
{
QgsGeometryCheck::Changes changes;
QgsGeometryCheckError *nonconsterr = const_cast<QgsGeometryCheckError *>( error );
error->check()->fixError( mFeaturePools, nonconsterr, method, QMap<QString, int>(), changes );
}
void QgsGeometryValidationService::onLayersAdded( const QList<QgsMapLayer *> &layers ) void QgsGeometryValidationService::onLayersAdded( const QList<QgsMapLayer *> &layers )
{ {
for ( QgsMapLayer *layer : layers ) for ( QgsMapLayer *layer : layers )
@ -122,7 +129,7 @@ void QgsGeometryValidationService::enableLayerChecks( QgsVectorLayer *layer )
qDeleteAll( mLayerCheckStates[layer].topologyChecks ); qDeleteAll( mLayerCheckStates[layer].topologyChecks );
// TODO: ownership and lifetime of the context!! // TODO: ownership and lifetime of the context!!
auto context = new QgsGeometryCheckContext( 1, mProject->crs(), mProject->transformContext() ); auto context = new QgsGeometryCheckContext( 8, mProject->crs(), mProject->transformContext() );
QList<QgsGeometryCheck *> layerChecks; QList<QgsGeometryCheck *> layerChecks;
QgsGeometryCheckRegistry *checkRegistry = QgsAnalysis::instance()->geometryCheckRegistry(); QgsGeometryCheckRegistry *checkRegistry = QgsAnalysis::instance()->geometryCheckRegistry();
@ -216,18 +223,33 @@ void QgsGeometryValidationService::triggerTopologyChecks( QgsVectorLayer *layer
mLayerCheckStates[layer].topologyCheckFeedbacks.clear(); mLayerCheckStates[layer].topologyCheckFeedbacks.clear();
} }
QgsFeatureIds checkFeatureIds = layer->editBuffer()->changedGeometries().keys().toSet(); QgsFeatureIds affectedFeatureIds = layer->editBuffer()->changedGeometries().keys().toSet();
checkFeatureIds.unite( layer->editBuffer()->addedFeatures().keys().toSet() ); affectedFeatureIds.unite( layer->editBuffer()->addedFeatures().keys().toSet() );
// TODO: ownership of these objects... // TODO: ownership of these objects...
QgsVectorLayerFeaturePool *featurePool = new QgsVectorLayerFeaturePool( layer ); QgsVectorLayerFeaturePool *featurePool = new QgsVectorLayerFeaturePool( layer );
QList<QgsGeometryCheckError *> &allErrors = mLayerCheckStates[layer].topologyCheckErrors; QList<QgsGeometryCheckError *> &allErrors = mLayerCheckStates[layer].topologyCheckErrors;
QMap<QString, QgsFeatureIds> layerIds; QMap<QString, QgsFeatureIds> layerIds;
QgsFeatureRequest request = QgsFeatureRequest( affectedFeatureIds ).setSubsetOfAttributes( QgsAttributeList() );
QgsFeatureIterator it = layer->getFeatures( request );
QgsFeature feature;
QgsRectangle area;
while ( it.nextFeature( feature ) )
{
area.combineExtentWith( feature.geometry().boundingBox() );
}
QgsFeatureRequest areaRequest = QgsFeatureRequest().setFilterRect( area );
QgsFeatureIds checkFeatureIds = featurePool->getFeatures( areaRequest );
layerIds.insert( layer->id(), checkFeatureIds ); layerIds.insert( layer->id(), checkFeatureIds );
QgsGeometryCheck::LayerFeatureIds layerFeatureIds( layerIds ); QgsGeometryCheck::LayerFeatureIds layerFeatureIds( layerIds );
QMap<QString, QgsFeaturePool *> featurePools; if ( !mFeaturePools.contains( layer->id() ) )
featurePools.insert( layer->id(), featurePool ); {
mFeaturePools.insert( layer->id(), featurePool );
}
const QList<QgsGeometryCheck *> checks = mLayerCheckStates[layer].topologyChecks; const QList<QgsGeometryCheck *> checks = mLayerCheckStates[layer].topologyChecks;
@ -237,7 +259,7 @@ void QgsGeometryValidationService::triggerTopologyChecks( QgsVectorLayer *layer
mLayerCheckStates[layer].topologyCheckFeedbacks = feedbacks.values(); mLayerCheckStates[layer].topologyCheckFeedbacks = feedbacks.values();
QFuture<void> future = QtConcurrent::map( checks, [featurePools, &allErrors, layerFeatureIds, layer, feedbacks, this]( const QgsGeometryCheck * check ) QFuture<void> future = QtConcurrent::map( checks, [&allErrors, layerFeatureIds, layer, feedbacks, this]( const QgsGeometryCheck * check )
{ {
// Watch out with the layer pointer in here. We are running in a thread, so we do not want to actually use it // Watch out with the layer pointer in here. We are running in a thread, so we do not want to actually use it
// except for using its address to report the error. // except for using its address to report the error.
@ -245,7 +267,7 @@ void QgsGeometryValidationService::triggerTopologyChecks( QgsVectorLayer *layer
QStringList messages; // Do we really need these? QStringList messages; // Do we really need these?
QgsFeedback *feedback = feedbacks.value( check ); QgsFeedback *feedback = feedbacks.value( check );
check->collectErrors( featurePools, errors, messages, feedback, layerFeatureIds ); check->collectErrors( mFeaturePools, errors, messages, feedback, layerFeatureIds );
QgsReadWriteLocker errorLocker( mTopologyCheckLock, QgsReadWriteLocker::Write ); QgsReadWriteLocker errorLocker( mTopologyCheckLock, QgsReadWriteLocker::Write );
allErrors.append( errors ); allErrors.append( errors );

View File

@ -31,6 +31,7 @@ class QgsSingleGeometryCheck;
class QgsSingleGeometryCheckError; class QgsSingleGeometryCheckError;
class QgsGeometryCheckError; class QgsGeometryCheckError;
class QgsFeedback; class QgsFeedback;
class QgsFeaturePool;
/** /**
* This service connects to all layers in a project and triggers validation * This service connects to all layers in a project and triggers validation
@ -64,6 +65,8 @@ class QgsGeometryValidationService : public QObject
*/ */
bool validationActive( QgsVectorLayer *layer, QgsFeatureId feature ) const; bool validationActive( QgsVectorLayer *layer, QgsFeatureId feature ) const;
void fixError( const QgsGeometryCheckError *error, int method );
signals: signals:
void geometryCheckStarted( QgsVectorLayer *layer, QgsFeatureId fid ); void geometryCheckStarted( QgsVectorLayer *layer, QgsFeatureId fid );
void geometryCheckCompleted( QgsVectorLayer *layer, QgsFeatureId fid, const QList<std::shared_ptr<QgsSingleGeometryCheckError>> &errors ); void geometryCheckCompleted( QgsVectorLayer *layer, QgsFeatureId fid, const QList<std::shared_ptr<QgsSingleGeometryCheckError>> &errors );
@ -101,6 +104,7 @@ class QgsGeometryValidationService : public QObject
QReadWriteLock mTopologyCheckLock; QReadWriteLock mTopologyCheckLock;
QHash<QgsVectorLayer *, VectorCheckState> mLayerCheckStates; QHash<QgsVectorLayer *, VectorCheckState> mLayerCheckStates;
QMap<QString, QgsFeaturePool *> mFeaturePools;
}; };
#endif // QGSGEOMETRYVALIDATIONSERVICE_H #endif // QGSGEOMETRYVALIDATIONSERVICE_H

View File

@ -28,13 +28,6 @@
<item row="3" column="0" colspan="3"> <item row="3" column="0" colspan="3">
<widget class="QWidget" name="mProblemDetailWidget" native="true"> <widget class="QWidget" name="mProblemDetailWidget" native="true">
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QPushButton" name="mZoomToProblemButton">
<property name="text">
<string>Zoom To Problem</string>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QPushButton" name="mZoomToFeatureButton"> <widget class="QPushButton" name="mZoomToFeatureButton">
<property name="text"> <property name="text">
@ -42,6 +35,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QPushButton" name="mZoomToProblemButton">
<property name="text">
<string>Zoom To Problem</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2"> <item row="0" column="0" colspan="2">
<widget class="QLabel" name="mProblemDescriptionLabel"> <widget class="QLabel" name="mProblemDescriptionLabel">
<property name="text"> <property name="text">
@ -49,6 +49,11 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0" colspan="2">
<widget class="QWidget" name="mResolutionWidget" native="true">
<layout class="QVBoxLayout" name="verticalLayout"/>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -123,6 +128,7 @@
<include location="../../images/images.qrc"/> <include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/> <include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/> <include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
</resources> </resources>
<connections/> <connections/>
</ui> </ui>