QGIS API Documentation 3.41.0-Master (cea29feecf2)
Loading...
Searching...
No Matches
qgsvaliditycheckresultswidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsvaliditycheckresultswidget.cpp
3 ----------------------------------
4 begin : November 2018
5 copyright : (C) 2018 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17#include "moc_qgsvaliditycheckresultswidget.cpp"
19#include "qgsapplication.h"
20#include "qgsfeedback.h"
22#include <QProgressDialog>
23#include <QDialogButtonBox>
24#include <QPushButton>
25
26//
27// QgsValidityCheckResultsModel
28//
29
30QgsValidityCheckResultsModel::QgsValidityCheckResultsModel( const QList<QgsValidityCheckResult> &results, QObject *parent )
31 : QAbstractItemModel( parent )
32 , mResults( results )
33{
34}
35
36QModelIndex QgsValidityCheckResultsModel::index( int row, int column, const QModelIndex &parent ) const
37{
38 Q_UNUSED( parent )
39 return createIndex( row, column );
40}
41
42QModelIndex QgsValidityCheckResultsModel::parent( const QModelIndex &child ) const
43{
44 Q_UNUSED( child )
45 return QModelIndex();
46}
47
48int QgsValidityCheckResultsModel::rowCount( const QModelIndex &parent ) const
49{
50 Q_UNUSED( parent )
51 return mResults.count();
52}
53
54int QgsValidityCheckResultsModel::columnCount( const QModelIndex &parent ) const
55{
56 Q_UNUSED( parent )
57 return 1;
58}
59
60QVariant QgsValidityCheckResultsModel::data( const QModelIndex &index, int role ) const
61{
62 if ( index.row() >= mResults.count() || index.row() < 0 )
63 return QVariant();
64
65 const QgsValidityCheckResult &res = mResults.at( index.row() );
66 switch ( role )
67 {
68 case Qt::DisplayRole:
69 case Qt::ToolTipRole:
70 return res.title;
71
73 return res.detailedDescription;
74
75 case Qt::DecorationRole:
76 switch ( res.type )
77 {
79 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconCritical.svg" ) );
80
82 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconWarning.svg" ) );
83 }
84 break;
85
86 default:
87 return QVariant();
88 }
89 return QVariant();
90}
91
92//
93// QgsValidityCheckResultsWidget
94//
95
97 : QWidget( parent )
98{
99 setupUi( this );
100}
101
102void QgsValidityCheckResultsWidget::setResults( const QList<QgsValidityCheckResult> &results )
103{
104 if ( mResultsModel )
105 mResultsModel->deleteLater();
106
107 mResultsModel = new QgsValidityCheckResultsModel( results, this );
108 mResultsListView->setModel( mResultsModel );
109
110 connect( mResultsListView->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsValidityCheckResultsWidget::selectionChanged );
111
112 if ( mResultsModel->rowCount() > 0 )
113 {
114 // auto select first result in list
115 const QModelIndex firstResult( mResultsModel->index( 0, 0, QModelIndex() ) );
116 mResultsListView->selectionModel()->select( firstResult, QItemSelectionModel::ClearAndSelect );
117 selectionChanged( firstResult, QModelIndex() );
118 }
119
120 mDescriptionLabel->hide();
121}
122
123void QgsValidityCheckResultsWidget::setDescription( const QString &description )
124{
125 mDescriptionLabel->setText( description );
126 mDescriptionLabel->setVisible( !description.isEmpty() );
127}
128
129bool QgsValidityCheckResultsWidget::runChecks( int type, const QgsValidityCheckContext *context, const QString &title, const QString &description, QWidget *parent )
130{
131 std::unique_ptr<QgsFeedback> feedback = std::make_unique<QgsFeedback>();
132 std::unique_ptr<QProgressDialog> progressDialog = std::make_unique<QProgressDialog>( tr( "Running Checks…" ), tr( "Abort" ), 0, 100, parent );
133 progressDialog->setWindowTitle( title );
134
135 QgsProxyProgressTask *proxyTask = new QgsProxyProgressTask( tr( "Running Checks" ) );
136
137 connect( feedback.get(), &QgsFeedback::progressChanged, progressDialog.get(), [&]( double progress ) {
138 progressDialog->setValue( static_cast<int>( progress ) );
139 progressDialog->setLabelText( feedback->property( "progress" ).toString() );
140
141 proxyTask->setProxyProgress( progress );
142
143#ifdef Q_OS_LINUX
144 // One iteration is actually enough on Windows to get good interactivity
145 // whereas on Linux we must allow for far more iterations.
146 int nIters = 0;
147 while ( ++nIters < 100 )
148#endif
149 {
150 QCoreApplication::processEvents();
151 }
152 } );
153 connect( progressDialog.get(), &QProgressDialog::canceled, progressDialog.get(), [&] {
154 feedback->cancel();
155 } );
156
157 QgsApplication::taskManager()->addTask( proxyTask );
158
159 const QList<QgsValidityCheckResult> results = QgsApplication::validityCheckRegistry()->runChecks( type, context, feedback.get() );
160
161 proxyTask->finalize( true );
162
163 if ( feedback->isCanceled() )
164 return false;
165
166 if ( results.empty() )
167 return true;
168
170 w->setResults( results );
171 w->setDescription( description );
172
173 bool hasCritical = false;
174 for ( const QgsValidityCheckResult &res : results )
175 {
176 if ( res.type == QgsValidityCheckResult::Critical )
177 {
178 hasCritical = true;
179 break;
180 }
181 }
182
183 QVBoxLayout *l = new QVBoxLayout();
184 l->addWidget( w );
185
186 QDialog dlg( parent );
187 dlg.setWindowTitle( title );
188
189 QDialogButtonBox *buttons = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, &dlg );
190 connect( buttons, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
191 connect( buttons, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
192 if ( hasCritical )
193 {
194 buttons->button( QDialogButtonBox::Ok )->setEnabled( false );
195 buttons->button( QDialogButtonBox::Ok )->setToolTip( tr( "Critical errors prevent this task from proceeding. Please address these issues and then retry." ) );
196 }
197
198 l->addWidget( buttons );
199
200 dlg.setLayout( l );
201
202 return dlg.exec();
203}
204
205void QgsValidityCheckResultsWidget::selectionChanged( const QModelIndex &current, const QModelIndex & )
206{
207 const QString desc = mResultsModel->data( current, static_cast<int>( QgsValidityCheckResultsModel::CustomRole::Description ) ).toString();
208 mDetailedDescriptionTextBrowser->setHtml( desc );
209}
static QgsValidityCheckRegistry * validityCheckRegistry()
Returns the application's validity check registry, used for managing validity checks.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QgsTaskManager * taskManager()
Returns the application's task manager, used for managing application wide background task handling.
void progressChanged(double progress)
Emitted when the feedback object reports a progress change.
A QgsTask shell which proxies progress reports.
long addTask(QgsTask *task, int priority=0)
Adds a task to the manager.
Base class for validity check contexts.
QList< QgsValidityCheckResult > runChecks(int type, const QgsValidityCheckContext *context, QgsFeedback *feedback) const
Runs all checks of the specified type and returns a list of results.
Represents an individual result from a validity check run by a QgsAbstractValidityCheck subclass.
@ Critical
Critical error - notify user of result and prevent operation from proceeding.
@ Warning
Warning only, allow operation to proceed but notify user of result.
QString detailedDescription
Detailed description of the result (translated), giving users enough detail for them to resolve the e...
QString title
A short, translated string summarising the result.
A QAbstractItemModel subclass for displaying the results from a QgsAbstractValidityCheck.
QgsValidityCheckResultsModel(const QList< QgsValidityCheckResult > &results, QObject *parent=nullptr)
Constructor for QgsValidityCheckResultsModel, showing the specified list of checks results.
QModelIndex parent(const QModelIndex &child) const override
QModelIndex index(int row, int column, const QModelIndex &parent) const override
@ Description
Result detailed description.
int columnCount(const QModelIndex &parent) const override
QVariant data(const QModelIndex &index, int role) const override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
A reusable widget which displays a summary of the results from a QgsAbstractValidityCheck (or checks)...
QgsValidityCheckResultsWidget(QWidget *parent)
Constructor for QgsValidityCheckResultsWidget, with the specified parent widget.
void setDescription(const QString &description)
Sets a description label to show at the top of the widget, e.g.
static bool runChecks(int type, const QgsValidityCheckContext *context, const QString &title, const QString &description, QWidget *parent=nullptr)
Runs all registered validity checks of the given type, and if any warnings or critical errors are enc...
void setResults(const QList< QgsValidityCheckResult > &results)
Sets the list of check results to show in the dialog.