QGIS API Documentation 3.99.0-Master (e9821da5c6b)
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
18#include "qgsapplication.h"
19#include "qgsfeedback.h"
22
23#include <QDialogButtonBox>
24#include <QProgressDialog>
25#include <QPushButton>
26#include <QString>
27
28#include "moc_qgsvaliditycheckresultswidget.cpp"
29
30using namespace Qt::StringLiterals;
31
32//
33// QgsValidityCheckResultsModel
34//
35
36QgsValidityCheckResultsModel::QgsValidityCheckResultsModel( const QList<QgsValidityCheckResult> &results, QObject *parent )
37 : QAbstractItemModel( parent )
38 , mResults( results )
39{
40}
41
42QModelIndex QgsValidityCheckResultsModel::index( int row, int column, const QModelIndex &parent ) const
43{
44 Q_UNUSED( parent )
45 return createIndex( row, column );
46}
47
48QModelIndex QgsValidityCheckResultsModel::parent( const QModelIndex &child ) const
49{
50 Q_UNUSED( child )
51 return QModelIndex();
52}
53
54int QgsValidityCheckResultsModel::rowCount( const QModelIndex &parent ) const
55{
56 Q_UNUSED( parent )
57 return mResults.count();
58}
59
61{
62 Q_UNUSED( parent )
63 return 1;
64}
65
66QVariant QgsValidityCheckResultsModel::data( const QModelIndex &index, int role ) const
67{
68 if ( index.row() >= mResults.count() || index.row() < 0 )
69 return QVariant();
70
71 const QgsValidityCheckResult &res = mResults.at( index.row() );
72 switch ( role )
73 {
74 case Qt::DisplayRole:
75 case Qt::ToolTipRole:
76 return res.title;
77
79 return res.detailedDescription;
80
81 case Qt::DecorationRole:
82 switch ( res.type )
83 {
85 return QgsApplication::getThemeIcon( u"/mIconCritical.svg"_s );
86
88 return QgsApplication::getThemeIcon( u"/mIconWarning.svg"_s );
89 }
90 break;
91
92 default:
93 return QVariant();
94 }
95 return QVariant();
96}
97
98//
99// QgsValidityCheckResultsWidget
100//
101
103 : QWidget( parent )
104{
105 setupUi( this );
106}
107
108void QgsValidityCheckResultsWidget::setResults( const QList<QgsValidityCheckResult> &results )
109{
110 if ( mResultsModel )
111 mResultsModel->deleteLater();
112
113 mResultsModel = new QgsValidityCheckResultsModel( results, this );
114 mResultsListView->setModel( mResultsModel );
115
116 connect( mResultsListView->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsValidityCheckResultsWidget::selectionChanged );
117
118 if ( mResultsModel->rowCount() > 0 )
119 {
120 // auto select first result in list
121 const QModelIndex firstResult( mResultsModel->index( 0, 0, QModelIndex() ) );
122 mResultsListView->selectionModel()->select( firstResult, QItemSelectionModel::ClearAndSelect );
123 selectionChanged( firstResult, QModelIndex() );
124 }
125
126 mDescriptionLabel->hide();
127}
128
129void QgsValidityCheckResultsWidget::setDescription( const QString &description )
130{
131 mDescriptionLabel->setText( description );
132 mDescriptionLabel->setVisible( !description.isEmpty() );
133}
134
135bool QgsValidityCheckResultsWidget::runChecks( int type, const QgsValidityCheckContext *context, const QString &title, const QString &description, QWidget *parent )
136{
137 auto feedback = std::make_unique<QgsFeedback>();
138 auto progressDialog = std::make_unique<QProgressDialog>( tr( "Running Checks…" ), tr( "Abort" ), 0, 100, parent );
139 progressDialog->setWindowTitle( title );
140
141 QgsProxyProgressTask *proxyTask = new QgsProxyProgressTask( tr( "Running Checks" ) );
142
143 connect( feedback.get(), &QgsFeedback::progressChanged, progressDialog.get(), [&]( double progress ) {
144 progressDialog->setValue( static_cast<int>( progress ) );
145 progressDialog->setLabelText( feedback->property( "progress" ).toString() );
146
147 proxyTask->setProxyProgress( progress );
148
149#ifdef Q_OS_LINUX
150 // One iteration is actually enough on Windows to get good interactivity
151 // whereas on Linux we must allow for far more iterations.
152 int nIters = 0;
153 while ( ++nIters < 100 )
154#endif
155 {
156 QCoreApplication::processEvents();
157 }
158 } );
159 connect( progressDialog.get(), &QProgressDialog::canceled, progressDialog.get(), [&] {
160 feedback->cancel();
161 } );
162
163 QgsApplication::taskManager()->addTask( proxyTask );
164
165 const QList<QgsValidityCheckResult> results = QgsApplication::validityCheckRegistry()->runChecks( type, context, feedback.get() );
166
167 proxyTask->finalize( true );
168
169 if ( feedback->isCanceled() )
170 return false;
171
172 if ( results.empty() )
173 return true;
174
176 w->setResults( results );
177 w->setDescription( description );
178
179 bool hasCritical = false;
180 for ( const QgsValidityCheckResult &res : results )
181 {
182 if ( res.type == QgsValidityCheckResult::Critical )
183 {
184 hasCritical = true;
185 break;
186 }
187 }
188
189 QVBoxLayout *l = new QVBoxLayout();
190 l->addWidget( w );
191
192 QDialog dlg( parent );
193 dlg.setWindowTitle( title );
194
195 QDialogButtonBox *buttons = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, &dlg );
196 connect( buttons, &QDialogButtonBox::accepted, &dlg, &QDialog::accept );
197 connect( buttons, &QDialogButtonBox::rejected, &dlg, &QDialog::reject );
198 if ( hasCritical )
199 {
200 buttons->button( QDialogButtonBox::Ok )->setEnabled( false );
201 buttons->button( QDialogButtonBox::Ok )->setToolTip( tr( "Critical errors prevent this task from proceeding. Please address these issues and then retry." ) );
202 }
203
204 l->addWidget( buttons );
205
206 dlg.setLayout( l );
207
208 return dlg.exec();
209}
210
211void QgsValidityCheckResultsWidget::selectionChanged( const QModelIndex &current, const QModelIndex & )
212{
213 const QString desc = mResultsModel->data( current, static_cast<int>( QgsValidityCheckResultsModel::CustomRole::Description ) ).toString();
214 mDetailedDescriptionTextBrowser->setHtml( desc );
215}
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.
QgsValidityCheckResult::Type type
Result type.
@ 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
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.