QGIS API Documentation  2.99.0-Master (dcec6bb)
qgssublayersdialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssublayersdialog.cpp - dialog for selecting sublayers
3  ---------------------
4  begin : January 2009
5  copyright : (C) 2009 by Florian El Ahdab
6  email : felahdab 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 
16 #include "qgssublayersdialog.h"
17 #include "qgslogger.h"
18 #include "qgssettings.h"
19 
20 #include <QTableWidgetItem>
21 #include <QPushButton>
22 
24 class SubLayerItem : public QTreeWidgetItem
25 {
26  public:
27  SubLayerItem( const QStringList &strings, int type = QTreeWidgetItem::Type )
28  : QTreeWidgetItem( strings, type )
29  {}
30 
31  bool operator <( const QTreeWidgetItem &other ) const
32  {
33  QgsSublayersDialog *d = qobject_cast<QgsSublayersDialog *>( treeWidget()->parent() );
34  int col = treeWidget()->sortColumn();
35 
36  if ( col == 0 || ( col > 0 && d->countColumn() == col ) )
37  return text( col ).toInt() < other.text( col ).toInt();
38  else
39  return text( col ) < other.text( col );
40  }
41 };
43 
44 QgsSublayersDialog::QgsSublayersDialog( ProviderType providerType, const QString &name,
45  QWidget *parent, Qt::WindowFlags fl )
46  : QDialog( parent, fl )
47  , mName( name )
48 {
49  setupUi( this );
50 
51  if ( providerType == QgsSublayersDialog::Ogr )
52  {
53  setWindowTitle( tr( "Select vector layers to add..." ) );
54  layersTable->setHeaderLabels( QStringList() << tr( "Layer ID" ) << tr( "Layer name" )
55  << tr( "Number of features" ) << tr( "Geometry type" ) );
56  mShowCount = true;
57  mShowType = true;
58  }
59  else if ( providerType == QgsSublayersDialog::Gdal )
60  {
61  setWindowTitle( tr( "Select raster layers to add..." ) );
62  layersTable->setHeaderLabels( QStringList() << tr( "Layer ID" ) << tr( "Layer name" ) );
63  }
64  else
65  {
66  setWindowTitle( tr( "Select layers to add..." ) );
67  layersTable->setHeaderLabels( QStringList() << tr( "Layer ID" ) << tr( "Layer name" )
68  << tr( "Type" ) );
69  mShowType = true;
70  }
71 
72  // add a "Select All" button - would be nicer with an icon
73  QPushButton *button = new QPushButton( tr( "Select All" ) );
74  buttonBox->addButton( button, QDialogButtonBox::ActionRole );
75  connect( button, &QAbstractButton::pressed, layersTable, &QTreeView::selectAll );
76  // connect( pbnSelectNone, SIGNAL( pressed() ), SLOT( layersTable->selectNone() ) );
77 
78  QgsSettings settings;
79  restoreGeometry( settings.value( "/Windows/" + mName + "SubLayers/geometry" ).toByteArray() );
80 
81  // Checkbox about adding sublayers to a group
82  if ( mShowAddToGroupCheckbox )
83  {
84  mCheckboxAddToGroup = new QCheckBox( tr( "Add layers to a group" ) );
85  bool addToGroup = settings.value( QStringLiteral( "/qgis/openSublayersInGroup" ), false ).toBool();
86  mCheckboxAddToGroup->setChecked( addToGroup );
87  buttonBox->addButton( mCheckboxAddToGroup, QDialogButtonBox::ActionRole );
88  }
89 }
90 
92 {
93  QgsSettings settings;
94  settings.setValue( "/Windows/" + mName + "SubLayers/geometry", saveGeometry() );
95  settings.setValue( "/Windows/" + mName + "SubLayers/headerState",
96  layersTable->header()->saveState() );
97 }
98 
99 static bool _isLayerIdUnique( int layerId, QTreeWidget *layersTable )
100 {
101  int count = 0;
102  for ( int j = 0; j < layersTable->topLevelItemCount(); j++ )
103  {
104  if ( layersTable->topLevelItem( j )->text( 0 ).toInt() == layerId )
105  {
106  count++;
107  }
108  }
109  return count == 1;
110 }
111 
113 {
114  LayerDefinitionList list;
115  for ( int i = 0; i < layersTable->selectedItems().size(); i++ )
116  {
117  QTreeWidgetItem *item = layersTable->selectedItems().at( i );
118 
119  LayerDefinition def;
120  def.layerId = item->text( 0 ).toInt();
121  def.layerName = item->text( 1 );
122  if ( mShowType )
123  {
124  // If there are more sub layers of the same name (virtual for geometry types),
125  // add geometry type
126  if ( !_isLayerIdUnique( def.layerId, layersTable ) )
127  def.type = item->text( mShowCount ? 3 : 2 );
128  }
129 
130  list << def;
131  }
132  return list;
133 }
134 
135 
137 {
138  Q_FOREACH ( const LayerDefinition &item, list )
139  {
140  QStringList elements;
141  elements << QString::number( item.layerId ) << item.layerName;
142  if ( mShowCount )
143  elements << QString::number( item.count );
144  if ( mShowType )
145  elements << item.type;
146  layersTable->addTopLevelItem( new SubLayerItem( elements ) );
147  }
148 
149  // resize columns
150  QgsSettings settings;
151  QByteArray ba = settings.value( "/Windows/" + mName + "SubLayers/headerState" ).toByteArray();
152  if ( ! ba.isNull() )
153  {
154  layersTable->header()->restoreState( ba );
155  }
156  else
157  {
158  for ( int i = 0; i < layersTable->columnCount(); i++ )
159  layersTable->resizeColumnToContents( i );
160  layersTable->setColumnWidth( 1, layersTable->columnWidth( 1 ) + 10 );
161  }
162 }
163 
164 // override exec() instead of using showEvent()
165 // because in some case we don't want the dialog to appear (depending on user settings)
166 // TODO alert the user when dialog is not opened
168 {
169  QgsSettings settings;
170  QString promptLayers = settings.value( QStringLiteral( "qgis/promptForSublayers" ), 1 ).toString();
171 
172  // make sure three are sublayers to choose
173  if ( layersTable->topLevelItemCount() == 0 )
174  return QDialog::Rejected;
175 
176  // check promptForSublayers settings - perhaps this should be in QgsDataSource instead?
177  if ( promptLayers == QLatin1String( "no" ) )
178  return QDialog::Rejected;
179  else if ( promptLayers == QLatin1String( "all" ) )
180  {
181  layersTable->selectAll();
182  return QDialog::Accepted;
183  }
184 
185  // if there is only 1 sublayer (probably the main layer), just select that one and return
186  if ( layersTable->topLevelItemCount() == 1 )
187  {
188  layersTable->selectAll();
189  return QDialog::Accepted;
190  }
191 
192  layersTable->sortByColumn( 1, Qt::AscendingOrder );
193  layersTable->setSortingEnabled( true );
194 
195  // if we got here, disable override cursor, open dialog and return result
196  // TODO add override cursor where it is missing (e.g. when opening via "Add Raster")
197  QCursor cursor;
198  bool overrideCursor = nullptr != QApplication::overrideCursor();
199  if ( overrideCursor )
200  {
201  cursor = QCursor( * QApplication::overrideCursor() );
202  QApplication::restoreOverrideCursor();
203  }
204  int ret = QDialog::exec();
205  if ( overrideCursor )
206  QApplication::setOverrideCursor( cursor );
207 
208  if ( mCheckboxAddToGroup )
209  settings.setValue( QStringLiteral( "/qgis/openSublayersInGroup" ), mCheckboxAddToGroup->isChecked() );
210  return ret;
211 }
QString layerName
Name of the layer (not necessarily unique)
int layerId
Identifier of the layer (one unique layer id may have multiple types though)
This class is a composition of two QSettings instances:
Definition: qgssettings.h:54
QgsSublayersDialog(ProviderType providerType, const QString &name, QWidget *parent=nullptr, Qt::WindowFlags fl=0)
QList< QgsSublayersDialog::LayerDefinition > LayerDefinitionList
List of layer definitions for the purpose of this dialog.
bool mShowType
Whether to show type in the table.
bool mShowCount
Whether to show number of features in the table.
void setValue(const QString &key, const QVariant &value, const QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
int count
Number of features (might be unused)
void populateLayerTable(const LayerDefinitionList &list)
Populate the table with layers.
QString type
Extra type depending on the use (e.g. geometry type for vector sublayers)
int countColumn() const
Return column with count or -1.
LayerDefinitionList selection()
Returns list of selected layers.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
A structure that defines layers for the purpose of this dialog.