QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgsprocessingmatrixparameterdialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsprocessingmatrixparameterdialog.cpp
3  ------------------------------------
4  Date : February 2019
5  Copyright : (C) 2019 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 "qgsgui.h"
18 #include <QStandardItemModel>
19 #include <QStandardItem>
20 #include <QPushButton>
21 #include <QLineEdit>
22 #include <QToolButton>
23 
25 
26 QgsProcessingMatrixParameterPanelWidget::QgsProcessingMatrixParameterPanelWidget( QWidget *parent, const QgsProcessingParameterMatrix *param, const QVariantList &initialTable )
27  : QgsPanelWidget( parent )
28  , mParam( param )
29 {
30  setupUi( this );
31 
33 
34  mTblView->setSelectionBehavior( QAbstractItemView::SelectRows );
35  mTblView->setSelectionMode( QAbstractItemView::ExtendedSelection );
36 
37  mButtonAdd = new QPushButton( tr( "Add Row" ) );
38  mButtonBox->addButton( mButtonAdd, QDialogButtonBox::ActionRole );
39 
40  mButtonRemove = new QPushButton( tr( "Remove Row(s)" ) );
41  mButtonBox->addButton( mButtonRemove, QDialogButtonBox::ActionRole );
42 
43  mButtonRemoveAll = new QPushButton( tr( "Remove All" ) );
44  mButtonBox->addButton( mButtonRemoveAll, QDialogButtonBox::ActionRole );
45 
46  connect( mButtonBox->button( QDialogButtonBox::Ok ), &QPushButton::clicked, this, [ = ]
47  {
48  emit widgetChanged();
49  acceptPanel();
50  } );
51  connect( mButtonBox->button( QDialogButtonBox::Cancel ), &QPushButton::clicked, this, [ = ]
52  {
53  acceptPanel();
54  } );
55 
56  connect( mButtonAdd, &QPushButton::clicked, this, &QgsProcessingMatrixParameterPanelWidget::addRow );
57  connect( mButtonRemove, &QPushButton::clicked, this, &QgsProcessingMatrixParameterPanelWidget::deleteRow );
58  connect( mButtonRemoveAll, &QPushButton::clicked, this, &QgsProcessingMatrixParameterPanelWidget::deleteAllRows );
59 
60  if ( param && param->hasFixedNumberRows() )
61  {
62  mButtonAdd->setEnabled( false );
63  mButtonRemove->setEnabled( false );
64  mButtonRemoveAll->setEnabled( false );
65  }
66 
67  populateTable( initialTable );
68 }
69 
70 QVariantList QgsProcessingMatrixParameterPanelWidget::table() const
71 {
72  const int cols = mModel->columnCount();
73  const int rows = mModel->rowCount();
74  // Table MUST BE 1-dimensional to match core QgsProcessingParameterMatrix expectations
75  QVariantList res;
76  res.reserve( cols * rows );
77  for ( int row = 0; row < rows; ++row )
78  {
79  for ( int col = 0; col < cols; ++col )
80  {
81  res << mModel->item( row, col )->text();
82  }
83  }
84  return res;
85 }
86 
87 void QgsProcessingMatrixParameterPanelWidget::addRow()
88 {
89  QList< QStandardItem * > items;
90  for ( int i = 0; i < mTblView->model()->columnCount(); ++i )
91  {
92  items << new QStandardItem( '0' );
93  }
94  mModel->appendRow( items );
95 }
96 
97 void QgsProcessingMatrixParameterPanelWidget::deleteRow()
98 {
99  QModelIndexList selected = mTblView->selectionModel()->selectedRows();
100  QSet< int > rows;
101  rows.reserve( selected.count() );
102  for ( const QModelIndex &i : selected )
103  rows << i.row();
104 
105  QList< int > rowsToDelete = qgis::setToList( rows );
106  std::sort( rowsToDelete.begin(), rowsToDelete.end(), std::greater<int>() );
107  mTblView->setUpdatesEnabled( false );
108  for ( int i : std::as_const( rowsToDelete ) )
109  mModel->removeRows( i, 1 );
110 
111  mTblView->setUpdatesEnabled( true );
112 }
113 
114 void QgsProcessingMatrixParameterPanelWidget::deleteAllRows()
115 {
116  mModel->clear();
117  if ( mParam )
118  mModel->setHorizontalHeaderLabels( mParam->headers() );
119 }
120 
121 void QgsProcessingMatrixParameterPanelWidget::populateTable( const QVariantList &contents )
122 {
123  if ( !mParam )
124  return;
125 
126  const int cols = mParam->headers().count();
127  const int rows = contents.length() / cols;
128  mModel = new QStandardItemModel( rows, cols, this );
129  mModel->setHorizontalHeaderLabels( mParam->headers() );
130 
131  for ( int row = 0; row < rows; ++row )
132  {
133  for ( int col = 0; col < cols; ++col )
134  {
135  QStandardItem *item = new QStandardItem( contents.at( row * cols + col ).toString() );
136  mModel->setItem( row, col, item );
137  }
138  }
139  mTblView->setModel( mModel );
140 }
141 
142 //
143 // QgsProcessingMatrixParameterPanel
144 //
145 
146 QgsProcessingMatrixParameterPanel::QgsProcessingMatrixParameterPanel( QWidget *parent, const QgsProcessingParameterMatrix *param )
147  : QWidget( parent )
148  , mParam( param )
149 {
150  QHBoxLayout *hl = new QHBoxLayout();
151  hl->setContentsMargins( 0, 0, 0, 0 );
152 
153  mLineEdit = new QLineEdit();
154  mLineEdit->setEnabled( false );
155  hl->addWidget( mLineEdit, 1 );
156 
157  mToolButton = new QToolButton();
158  mToolButton->setText( QString( QChar( 0x2026 ) ) );
159  hl->addWidget( mToolButton );
160 
161  setLayout( hl );
162 
163  if ( mParam )
164  {
165  for ( int row = 0; row < mParam->numberRows(); ++row )
166  {
167  for ( int col = 0; col < mParam->headers().count(); ++col )
168  {
169  mTable.append( '0' );
170  }
171  }
172  mLineEdit->setText( tr( "Fixed table (%1x%2)" ).arg( mParam->numberRows() ).arg( mParam->headers().count() ) );
173  }
174 
175  connect( mToolButton, &QToolButton::clicked, this, &QgsProcessingMatrixParameterPanel::showDialog );
176 }
177 
178 void QgsProcessingMatrixParameterPanel::setValue( const QVariantList &value )
179 {
180  mTable = value;
181  updateSummaryText();
182  emit changed();
183 }
184 
185 void QgsProcessingMatrixParameterPanel::showDialog()
186 {
187  if ( QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this ) )
188  {
189  QgsProcessingMatrixParameterPanelWidget *widget = new QgsProcessingMatrixParameterPanelWidget( this, mParam, mTable );
190 
191  widget->setPanelTitle( mParam->description() );
192 
193  panel->openPanel( widget );
194 
195  connect( widget, &QgsPanelWidget::widgetChanged, this, [ = ]
196  {
197  setValue( widget->table() );
198  } );
199  }
200 }
201 
202 void QgsProcessingMatrixParameterPanel::updateSummaryText()
203 {
204  if ( mParam )
205  mLineEdit->setText( tr( "Fixed table (%1x%2)" ).arg( mTable.count() / mParam->headers().count() ).arg( mParam->headers().count() ) );
206 }
207 
208 
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition: qgsgui.cpp:156
Base class for any widget that can be shown as a inline panel.
void widgetChanged()
Emitted when the widget state changes.
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
A table (matrix) parameter for processing algorithms.
bool hasFixedNumberRows() const
Returns whether the table has a fixed number of rows.