QGIS API Documentation  2.99.0-Master (bdf46d7)
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 
23 
24 QgsSublayersDialog::QgsSublayersDialog( ProviderType providerType, const QString &name,
25  QWidget *parent, Qt::WindowFlags fl )
26  : QDialog( parent, fl )
27  , mName( name )
28 {
29  setupUi( this );
30 
31  if ( providerType == QgsSublayersDialog::Ogr )
32  {
33  setWindowTitle( tr( "Select vector layers to add..." ) );
34  layersTable->setHeaderLabels( QStringList() << tr( "Layer ID" ) << tr( "Layer name" )
35  << tr( "Number of features" ) << tr( "Geometry type" ) );
36  mShowCount = true;
37  mShowType = true;
38  }
39  else if ( providerType == QgsSublayersDialog::Gdal )
40  {
41  setWindowTitle( tr( "Select raster layers to add..." ) );
42  layersTable->setHeaderLabels( QStringList() << tr( "Layer ID" ) << tr( "Layer name" ) );
43  }
44  else
45  {
46  setWindowTitle( tr( "Select layers to add..." ) );
47  layersTable->setHeaderLabels( QStringList() << tr( "Layer ID" ) << tr( "Layer name" )
48  << tr( "Type" ) );
49  mShowType = true;
50  }
51 
52  // add a "Select All" button - would be nicer with an icon
53  QPushButton *button = new QPushButton( tr( "Select All" ) );
54  buttonBox->addButton( button, QDialogButtonBox::ActionRole );
55  connect( button, &QAbstractButton::pressed, layersTable, &QTreeView::selectAll );
56  // connect( pbnSelectNone, SIGNAL( pressed() ), SLOT( layersTable->selectNone() ) );
57 
58  QgsSettings settings;
59  restoreGeometry( settings.value( "/Windows/" + mName + "SubLayers/geometry" ).toByteArray() );
60 
61  // Checkbox about adding sublayers to a group
62  if ( mShowAddToGroupCheckbox )
63  {
64  mCheckboxAddToGroup = new QCheckBox( tr( "Add layers to a group" ) );
65  bool addToGroup = settings.value( QStringLiteral( "/qgis/openSublayersInGroup" ), false ).toBool();
66  mCheckboxAddToGroup->setChecked( addToGroup );
67  buttonBox->addButton( mCheckboxAddToGroup, QDialogButtonBox::ActionRole );
68  }
69 }
70 
72 {
73  QgsSettings settings;
74  settings.setValue( "/Windows/" + mName + "SubLayers/geometry", saveGeometry() );
75  settings.setValue( "/Windows/" + mName + "SubLayers/headerState",
76  layersTable->header()->saveState() );
77 }
78 
79 static bool _isLayerIdUnique( int layerId, QTreeWidget *layersTable )
80 {
81  int count = 0;
82  for ( int j = 0; j < layersTable->topLevelItemCount(); j++ )
83  {
84  if ( layersTable->topLevelItem( j )->text( 0 ).toInt() == layerId )
85  {
86  count++;
87  }
88  }
89  return count == 1;
90 }
91 
93 {
95  for ( int i = 0; i < layersTable->selectedItems().size(); i++ )
96  {
97  QTreeWidgetItem *item = layersTable->selectedItems().at( i );
98 
99  LayerDefinition def;
100  def.layerId = item->text( 0 ).toInt();
101  def.layerName = item->text( 1 );
102  if ( mShowType )
103  {
104  // If there are more sub layers of the same name (virtual for geometry types),
105  // add geometry type
106  if ( !_isLayerIdUnique( def.layerId, layersTable ) )
107  def.type = item->text( mShowCount ? 3 : 2 );
108  }
109 
110  list << def;
111  }
112  return list;
113 }
114 
115 
117 {
118  Q_FOREACH ( const LayerDefinition &item, list )
119  {
120  QStringList elements;
121  elements << QString::number( item.layerId ) << item.layerName;
122  if ( mShowCount )
123  elements << QString::number( item.count );
124  if ( mShowType )
125  elements << item.type;
126  layersTable->addTopLevelItem( new QTreeWidgetItem( elements ) );
127  }
128 
129  // resize columns
130  QgsSettings settings;
131  QByteArray ba = settings.value( "/Windows/" + mName + "SubLayers/headerState" ).toByteArray();
132  if ( ! ba.isNull() )
133  {
134  layersTable->header()->restoreState( ba );
135  }
136  else
137  {
138  for ( int i = 0; i < layersTable->columnCount(); i++ )
139  layersTable->resizeColumnToContents( i );
140  layersTable->setColumnWidth( 1, layersTable->columnWidth( 1 ) + 10 );
141  }
142 }
143 
144 // override exec() instead of using showEvent()
145 // because in some case we don't want the dialog to appear (depending on user settings)
146 // TODO alert the user when dialog is not opened
148 {
149  QgsSettings settings;
150  QString promptLayers = settings.value( QStringLiteral( "qgis/promptForSublayers" ), 1 ).toString();
151 
152  // make sure three are sublayers to choose
153  if ( layersTable->topLevelItemCount() == 0 )
154  return QDialog::Rejected;
155 
156  // check promptForSublayers settings - perhaps this should be in QgsDataSource instead?
157  if ( promptLayers == QLatin1String( "no" ) )
158  return QDialog::Rejected;
159  else if ( promptLayers == QLatin1String( "all" ) )
160  {
161  layersTable->selectAll();
162  return QDialog::Accepted;
163  }
164 
165  // if there is only 1 sublayer (probably the main layer), just select that one and return
166  if ( layersTable->topLevelItemCount() == 1 )
167  {
168  layersTable->selectAll();
169  return QDialog::Accepted;
170  }
171 
172  layersTable->sortByColumn( 1, Qt::AscendingOrder );
173  layersTable->setSortingEnabled( true );
174 
175  // if we got here, disable override cursor, open dialog and return result
176  // TODO add override cursor where it is missing (e.g. when opening via "Add Raster")
177  QCursor cursor;
178  bool overrideCursor = nullptr != QApplication::overrideCursor();
179  if ( overrideCursor )
180  {
181  cursor = QCursor( * QApplication::overrideCursor() );
182  QApplication::restoreOverrideCursor();
183  }
184  int ret = QDialog::exec();
185  if ( overrideCursor )
186  QApplication::setOverrideCursor( cursor );
187 
188  if ( mCheckboxAddToGroup )
189  settings.setValue( QStringLiteral( "/qgis/openSublayersInGroup" ), mCheckboxAddToGroup->isChecked() );
190  return ret;
191 }
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< 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)
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.
static bool _isLayerIdUnique(int layerId, QTreeWidget *layersTable)
A structure that defines layers for the purpose of this dialog.