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