QGIS API Documentation  3.25.0-Master (6b426f5f8a)
qgsdatabasetablecombobox.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsdatabasetablecombobox.cpp
3  --------------------------------
4  Date : March 2020
5  Copyright : (C) 2020 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 "qgsdatabasetablemodel.h"
18 #include "qgsapplication.h"
20 #include <QHBoxLayout>
21 #include <QToolButton>
22 
23 QgsDatabaseTableComboBox::QgsDatabaseTableComboBox( const QString &provider, const QString &connection, const QString &schema, QWidget *parent )
24  : QWidget( parent )
25  , mProvider( provider )
26  , mConnection( connection )
27  , mSchema( schema )
28 {
29  if ( !provider.isEmpty() && !connection.isEmpty() )
30  mModel = new QgsDatabaseTableModel( provider, connection, schema, this );
31  init();
32 }
33 
35  : QWidget( parent )
36  , mSchema( schema )
37 {
38  mModel = new QgsDatabaseTableModel( connection, schema, this );
39  init();
40 }
41 
43 {
44  mAllowEmpty = allowEmpty;
45  if ( mModel )
46  mModel->setAllowEmptyTable( allowEmpty );
47 }
48 
50 {
51  return mAllowEmpty;
52 }
53 
54 void QgsDatabaseTableComboBox::init()
55 {
56  mComboBox = new QComboBox();
57 
58  mSortModel = new QgsDatabaseTableComboBoxSortModel( this );
59  if ( mModel )
60  mSortModel->setSourceModel( mModel );
61  mSortModel->setSortRole( Qt::DisplayRole );
62  mSortModel->setSortLocaleAware( true );
63  mSortModel->setSortCaseSensitivity( Qt::CaseInsensitive );
64  mSortModel->setDynamicSortFilter( true );
65  mSortModel->sort( 0 );
66 
67  mComboBox->setModel( mSortModel );
68 
69  QHBoxLayout *l = new QHBoxLayout();
70  l->setContentsMargins( 0, 0, 0, 0 );
71  l->addWidget( mComboBox );
72 
73  QToolButton *refreshButton = new QToolButton();
74  refreshButton->setAutoRaise( true );
75  refreshButton->setToolTip( tr( "Refresh tables" ) );
76  refreshButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mActionRefresh.svg" ) ) );
77  l->addWidget( refreshButton );
78  setLayout( l );
79 
80  connect( refreshButton, &QToolButton::clicked, this, &QgsDatabaseTableComboBox::refreshTables );
81 
82  connect( mComboBox, static_cast < void ( QComboBox::* )( int ) > ( &QComboBox::activated ), this, &QgsDatabaseTableComboBox::indexChanged );
83  connect( mSortModel, &QAbstractItemModel::rowsInserted, this, &QgsDatabaseTableComboBox::rowsChanged );
84  connect( mSortModel, &QAbstractItemModel::rowsRemoved, this, &QgsDatabaseTableComboBox::rowsChanged );
85 }
86 
87 void QgsDatabaseTableComboBox::setTable( const QString &table, const QString &schema )
88 {
89  if ( schema == currentSchema() && table == currentTable() )
90  return;
91 
92  if ( table.isEmpty() )
93  {
94  if ( mAllowEmpty )
95  mComboBox->setCurrentIndex( 0 );
96  else
97  mComboBox->setCurrentIndex( -1 );
98 
99  emit tableChanged( QString() );
100  return;
101  }
102 
103  const QModelIndexList idxs = mSortModel->match( mSortModel->index( 0, 0 ), QgsDatabaseTableModel::RoleTableName, table, -1, Qt::MatchFixedString | Qt::MatchCaseSensitive );
104  for ( const QModelIndex &proxyIdx : idxs )
105  {
106  if ( proxyIdx.isValid() && proxyIdx.data( QgsDatabaseTableModel::RoleTableName ).toString() == table
107  && ( schema.isEmpty() || proxyIdx.data( QgsDatabaseTableModel::RoleSchema ).toString() == schema ) )
108  {
109  mComboBox->setCurrentIndex( proxyIdx.row() );
111  return;
112  }
113  }
114  mComboBox->setCurrentIndex( -1 );
115  emit tableChanged( QString() );
116 }
117 
118 void QgsDatabaseTableComboBox::setConnectionName( const QString &connection, const QString &provider )
119 {
120  if ( provider.isEmpty() && mConnection == connection )
121  return;
122 
123  if ( !provider.isEmpty() )
124  mProvider = provider;
125 
126  mConnection = connection;
127 
128  const QString oldTable = currentTable();
129  const QString oldSchema = currentSchema();
130  QgsDatabaseTableModel *oldModel = mModel;
131  if ( !mConnection.isEmpty() )
132  {
133  mModel = new QgsDatabaseTableModel( mProvider, mConnection, mSchema, this );
134  mModel->setAllowEmptyTable( mAllowEmpty );
135  }
136  else
137  mModel = nullptr;
138 
139  mSortModel->setSourceModel( mModel );
140  if ( oldModel )
141  oldModel->deleteLater();
142  if ( currentTable() != oldTable || currentSchema() != oldSchema )
143  setTable( oldTable, oldSchema );
144 }
145 
146 void QgsDatabaseTableComboBox::setSchema( const QString &schema )
147 {
148  if ( schema == mSchema )
149  return;
150  mSchema = schema;
151 
152  if ( !mProvider.isEmpty() && !mConnection.isEmpty() )
153  {
154  const QString oldTable = currentTable();
155  QgsDatabaseTableModel *oldModel = mModel;
156  mModel = new QgsDatabaseTableModel( mProvider, mConnection, mSchema, this );
157  mSortModel->setSourceModel( mModel );
158  oldModel->deleteLater();
159  setTable( oldTable );
160  }
161 }
162 
164 {
165  const QString oldSchema = currentSchema();
166  const QString oldTable = currentTable();
167  if ( mModel )
168  mModel->refresh();
169  setTable( oldTable, oldSchema );
170 }
171 
173 {
174  const QModelIndex proxyIndex = mSortModel->index( mComboBox->currentIndex(), 0 );
175  if ( !proxyIndex.isValid() )
176  {
177  return QString();
178  }
179 
180  return mSortModel->data( proxyIndex, QgsDatabaseTableModel::RoleSchema ).toString();
181 }
182 
184 {
185  const QModelIndex proxyIndex = mSortModel->index( mComboBox->currentIndex(), 0 );
186  if ( !proxyIndex.isValid() )
187  {
188  return QString();
189  }
190 
191  return mSortModel->data( proxyIndex, QgsDatabaseTableModel::RoleTableName ).toString();
192 }
193 
194 void QgsDatabaseTableComboBox::indexChanged( int i )
195 {
196  Q_UNUSED( i )
197  emit tableChanged( currentTable() );
198 }
199 
200 void QgsDatabaseTableComboBox::rowsChanged()
201 {
202  if ( mComboBox->count() == 1 || ( mAllowEmpty && mComboBox->count() == 2 && mComboBox->currentIndex() == 1 ) )
203  {
204  //currently selected connection item has changed
206  }
207  else if ( mComboBox->count() == 0 )
208  {
209  emit tableChanged( QString() );
210  }
211 }
212 
214 QgsDatabaseTableComboBoxSortModel::QgsDatabaseTableComboBoxSortModel( QObject *parent )
215  : QSortFilterProxyModel( parent )
216 {
217 
218 }
219 
220 bool QgsDatabaseTableComboBoxSortModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
221 {
222  // empty row is always first
223  if ( sourceModel()->data( left, QgsDatabaseTableModel::RoleEmpty ).toBool() )
224  return true;
225  else if ( sourceModel()->data( right, QgsDatabaseTableModel::RoleEmpty ).toBool() )
226  return false;
227 
228  // default mode is alphabetical order
229  const QString leftStr = sourceModel()->data( left ).toString();
230  const QString rightStr = sourceModel()->data( right ).toString();
231  return QString::localeAwareCompare( leftStr, rightStr ) < 0;
232 }
233 
The QgsAbstractDatabaseProviderConnection class provides common functionality for DB based connection...
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
void setSchema(const QString &schema)
Sets the schema from which to retrieve the available tables.
void tableChanged(const QString &table, const QString &schema=QString())
Emitted whenever the currently selected table changes.
void setTable(const QString &table, const QString &schema=QString())
Sets the current table selected in the combo box.
void setConnectionName(const QString &connection, const QString &provider=QString())
Sets the database connection name from which to retrieve the available tables.
void refreshTables()
Refreshes the list of available tables.
QString currentSchema() const
Returns the schema of the current table selected in the combo box.
bool allowEmptyTable() const
Returns true if the combobox allows the empty table ("not set") choice.
void setAllowEmptyTable(bool allowEmpty)
Sets whether an optional empty table ("not set") option is present in the combobox.
QgsDatabaseTableComboBox(const QString &provider, const QString &connection, const QString &schema=QString(), QWidget *parent=nullptr)
Constructor for QgsDatabaseTableComboBox, for the specified provider and connection.
QString currentTable() const
Returns the name of the current table selected in the combo box.
A model containing tables from a database connection.
void refresh()
Refreshes the table list by querying the underlying connection.
void setAllowEmptyTable(bool allowEmpty)
Sets whether an optional empty table ("not set") option is present in the model.
@ RoleEmpty
Entry is an empty entry.