QGIS API Documentation  3.13.0-Master (b73bd58cfb)
qgsorderbydialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgosorderbydialog.cpp
3 
4  ---------------------
5  begin : 20.12.2015
6  copyright : (C) 2015 by Matthias Kuhn
7  email : [email protected]
8  ***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
17 #include "qgsorderbydialog.h"
18 
21 #include "qgsvectorlayer.h"
22 
23 #include <QTableWidget>
24 #include <QKeyEvent>
25 
27  : QDialog( parent )
28  , mLayer( layer )
29 {
30  setupUi( this );
31 
32  mOrderByTableWidget->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );
33  mOrderByTableWidget->horizontalHeader()->setSectionResizeMode( 1, QHeaderView::ResizeToContents );
34  mOrderByTableWidget->horizontalHeader()->setSectionResizeMode( 2, QHeaderView::ResizeToContents );
35 
36  mOrderByTableWidget->installEventFilter( this );
37 
38  connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsOrderByDialog::showHelp );
39 }
40 
42 {
43  mOrderByTableWidget->setRowCount( orderBy.length() + 1 );
44 
45  int i = 0;
46  const auto constOrderBy = orderBy;
47  for ( const QgsFeatureRequest::OrderByClause &orderByClause : constOrderBy )
48  {
49  setRow( i, orderByClause );
50 
51  ++i;
52  }
53 
54  // Add an empty widget at the end
55  setRow( i, QgsFeatureRequest::OrderByClause( QString() ) );
56 }
57 
59 {
61 
62  for ( int i = 0; i < mOrderByTableWidget->rowCount(); ++i )
63  {
64  QString expressionText = static_cast<QgsFieldExpressionWidget *>( mOrderByTableWidget->cellWidget( i, 0 ) )->currentText();
65  bool isExpression = static_cast<QgsFieldExpressionWidget *>( mOrderByTableWidget->cellWidget( i, 0 ) )->isExpression();
66 
67  if ( ! expressionText.isEmpty() )
68  {
69  bool asc = true;
70  int ascIndex = static_cast<QComboBox *>( mOrderByTableWidget->cellWidget( i, 1 ) )->currentIndex();
71  if ( ascIndex == 1 )
72  asc = false;
73 
74  bool nullsFirst = false;
75  int nullsFirstIndex = static_cast<QComboBox *>( mOrderByTableWidget->cellWidget( i, 2 ) )->currentIndex();
76  if ( nullsFirstIndex == 1 )
77  nullsFirst = true;
78 
79  if ( !isExpression )
80  expressionText = QgsExpression::quotedColumnRef( expressionText );
81 
82  QgsFeatureRequest::OrderByClause orderByClause( expressionText, asc, nullsFirst );
83 
84  orderBy << orderByClause;
85  }
86  }
87 
88  return orderBy;
89 }
90 
91 void QgsOrderByDialog::onExpressionChanged( const QString &expression )
92 {
93  // The sender() is the field widget which is the cell widget of the first column
94  int row;
95  for ( row = 0; row < mOrderByTableWidget->rowCount(); ++row )
96  {
97  if ( mOrderByTableWidget->cellWidget( row, 0 ) == sender() )
98  {
99  break;
100  }
101  }
102 
103  if ( expression.isEmpty() && row != mOrderByTableWidget->rowCount() - 1 )
104  {
105  mOrderByTableWidget->removeRow( row );
106  }
107  else if ( !expression.isEmpty() && row == mOrderByTableWidget->rowCount() - 1 )
108  {
109  mOrderByTableWidget->insertRow( mOrderByTableWidget->rowCount() );
110  setRow( row + 1, QgsFeatureRequest::OrderByClause( QString() ) );
111  }
112 }
113 
114 void QgsOrderByDialog::setRow( int row, const QgsFeatureRequest::OrderByClause &orderByClause )
115 {
116  QgsFieldExpressionWidget *fieldExpression = new QgsFieldExpressionWidget();
117  fieldExpression->setLayer( mLayer );
118  fieldExpression->setField( orderByClause.expression().expression() );
119  connect( fieldExpression, static_cast < void ( QgsFieldExpressionWidget::* )( const QString & ) >( &QgsFieldExpressionWidget::fieldChanged ), this, &QgsOrderByDialog::onExpressionChanged );
120 
121  QComboBox *ascComboBox = new QComboBox();
122  ascComboBox->addItem( tr( "Ascending" ) );
123  ascComboBox->addItem( tr( "Descending" ) );
124  ascComboBox->setCurrentIndex( orderByClause.ascending() ? 0 : 1 );
125 
126  QComboBox *nullsFirstComboBox = new QComboBox();
127  nullsFirstComboBox->addItem( tr( "NULLs last" ) );
128  nullsFirstComboBox->addItem( tr( "NULLs first" ) );
129  nullsFirstComboBox->setCurrentIndex( orderByClause.nullsFirst() ? 1 : 0 );
130 
131  mOrderByTableWidget->setCellWidget( row, 0, fieldExpression );
132  mOrderByTableWidget->setCellWidget( row, 1, ascComboBox );
133  mOrderByTableWidget->setCellWidget( row, 2, nullsFirstComboBox );
134 }
135 
136 bool QgsOrderByDialog::eventFilter( QObject *obj, QEvent *e )
137 {
138  Q_UNUSED( obj )
139  Q_ASSERT( obj == mOrderByTableWidget );
140 
141  if ( e->type() == QEvent::KeyPress )
142  {
143  QKeyEvent *keyEvent = static_cast<QKeyEvent *>( e );
144 
145  if ( keyEvent->key() == Qt::Key_Delete )
146  {
147  if ( mOrderByTableWidget->currentRow() != mOrderByTableWidget->rowCount() - 1 )
148  mOrderByTableWidget->removeRow( mOrderByTableWidget->currentRow() );
149  return true;
150  }
151  }
152 
153  return QDialog::eventFilter( obj, e );
154 }
155 
156 void QgsOrderByDialog::showHelp()
157 {
158  QgsHelp::openHelp( QStringLiteral( "working_with_vector/vector_properties.html#layer-rendering" ) );
159 }
The QgsFieldExpressionWidget class reates a widget to choose fields and edit expressions It contains ...
bool nullsFirst() const
Set if NULLS should be returned first.
bool eventFilter(QObject *obj, QEvent *e) override
void setOrderBy(const QgsFeatureRequest::OrderBy &orderBy)
Set the order by to manage.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
bool ascending() const
Order ascending.
void setLayer(QgsMapLayer *layer)
Sets the layer used to display the fields and expression.
QString expression() const
Returns the original, unmodified expression string.
void fieldChanged(const QString &fieldName)
Emitted when the currently selected field changes.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
QgsExpression expression() const
The expression.
void setField(const QString &fieldName)
sets the current field or expression in the widget
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:36
QgsOrderByDialog(QgsVectorLayer *layer, QWidget *parent=nullptr)
Create a new order by dialog.
QgsFeatureRequest::OrderBy orderBy()
Gets the order by defined in the dialog.
Represents a vector layer which manages a vector based data sets.
Represents a list of OrderByClauses, with the most important first and the least important last...