QGIS API Documentation  3.2.0-Bonn (bc43194)
qgsmaplayerstylemanagerwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmaplayerstylemanagerwidget.cpp
3  ---------------------
4  begin : June 2016
5  copyright : (C) 2016 by Nathan Woodrow
6  email : woodrow dot nathan 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 #include <QAction>
16 #include <QVBoxLayout>
17 #include <QToolBar>
18 #include <QInputDialog>
19 #include <QMessageBox>
20 #include <QFileDialog>
21 
23 #include "qgssettings.h"
24 #include "qgslogger.h"
25 #include "qgsmaplayer.h"
26 #include "qgsmapcanvas.h"
29 #include "qgsvectordataprovider.h"
30 #include "qgsrasterdataprovider.h"
31 #include "qgsvectorlayer.h"
32 #include "qgsrasterlayer.h"
33 
34 
36  : QgsMapLayerConfigWidget( layer, canvas, parent )
37 {
38  mModel = new QStandardItemModel( this );
39  mStyleList = new QListView( this );
40  mStyleList->setModel( mModel );
41  mStyleList->setViewMode( QListView::ListMode );
42  mStyleList->setResizeMode( QListView::Adjust );
43 
44  QToolBar *toolbar = new QToolBar( this );
45  QAction *addAction = toolbar->addAction( tr( "Add" ) );
46  addAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "symbologyAdd.svg" ) ) );
47  connect( addAction, &QAction::triggered, this, &QgsMapLayerStyleManagerWidget::addStyle );
48  QAction *removeAction = toolbar->addAction( tr( "Remove Current" ) );
49  removeAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "symbologyRemove.svg" ) ) );
50  connect( removeAction, &QAction::triggered, this, &QgsMapLayerStyleManagerWidget::removeStyle );
51  QAction *loadFromFileAction = toolbar->addAction( tr( "Load Style" ) );
52  loadFromFileAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFileOpen.svg" ) ) );
53  connect( loadFromFileAction, &QAction::triggered, this, &QgsMapLayerStyleManagerWidget::loadStyle );
54  QAction *saveAsDefaultAction = toolbar->addAction( tr( "Save as Default" ) );
55  connect( saveAsDefaultAction, &QAction::triggered, this, &QgsMapLayerStyleManagerWidget::saveAsDefault );
56  QAction *loadDefaultAction = toolbar->addAction( tr( "Restore Default" ) );
57  connect( loadDefaultAction, &QAction::triggered, this, &QgsMapLayerStyleManagerWidget::loadDefault );
58 
59 
60  // Save style doesn't work correctly yet so just disable for now.
61 // QAction* saveToFileAction = toolbar->addAction( tr( "Save Style" ) );
62 // connect( saveToFileAction, SIGNAL( triggered() ), this, SLOT( saveStyle() ) );
63 
64  //broken connect - not sure what the purpose of this was?
65 // connect( canvas, &QgsMapCanvas::mapCanvasRefreshed, this, SLOT( updateCurrent() ) );
66 
67  connect( mStyleList, &QAbstractItemView::clicked, this, &QgsMapLayerStyleManagerWidget::styleClicked );
68 
69  setLayout( new QVBoxLayout() );
70  layout()->setContentsMargins( 0, 0, 0, 0 );
71  layout()->addWidget( toolbar );
72  layout()->addWidget( mStyleList );
73 
74  connect( mLayer->styleManager(), &QgsMapLayerStyleManager::currentStyleChanged, this, &QgsMapLayerStyleManagerWidget::currentStyleChanged );
75  connect( mLayer->styleManager(), &QgsMapLayerStyleManager::styleAdded, this, &QgsMapLayerStyleManagerWidget::styleAdded );
76  connect( mLayer->styleManager(), &QgsMapLayerStyleManager::styleRemoved, this, &QgsMapLayerStyleManagerWidget::styleRemoved );
77  connect( mLayer->styleManager(), &QgsMapLayerStyleManager::styleRenamed, this, &QgsMapLayerStyleManagerWidget::styleRenamed );
78 
79  mModel->clear();
80 
81  Q_FOREACH ( const QString name, mLayer->styleManager()->styles() )
82  {
83  QString stylename = name;
84  QStandardItem *item = new QStandardItem( stylename );
85  mModel->appendRow( item );
86  }
87 
88  QString active = mLayer->styleManager()->currentStyle();
89  currentStyleChanged( active );
90 }
91 
92 void QgsMapLayerStyleManagerWidget::styleClicked( const QModelIndex &index )
93 {
94  if ( !mLayer || !index.isValid() )
95  return;
96 
97  QString name = index.data().toString();
99 }
100 
101 void QgsMapLayerStyleManagerWidget::currentStyleChanged( const QString &name )
102 {
103  QList<QStandardItem *> items = mModel->findItems( name );
104  if ( items.isEmpty() )
105  return;
106 
107  QStandardItem *item = items.at( 0 );
108 
109  mStyleList->setCurrentIndex( item->index() );
110 }
111 
112 void QgsMapLayerStyleManagerWidget::styleAdded( const QString &name )
113 {
114  QgsDebugMsg( "Style added" );
115  QStandardItem *item = new QStandardItem( name );
116  mModel->appendRow( item );
117 }
118 
119 void QgsMapLayerStyleManagerWidget::styleRemoved( const QString &name )
120 {
121  QList<QStandardItem *> items = mModel->findItems( name );
122  if ( items.isEmpty() )
123  return;
124 
125  QStandardItem *item = items.at( 0 );
126  mModel->removeRow( item->row() );
127 }
128 
129 void QgsMapLayerStyleManagerWidget::styleRenamed( const QString &oldname, const QString &newname )
130 {
131  QList<QStandardItem *> items = mModel->findItems( oldname );
132  if ( items.isEmpty() )
133  return;
134 
135  QStandardItem *item = items.at( 0 );
136  item->setText( newname );
137 }
138 
139 void QgsMapLayerStyleManagerWidget::addStyle()
140 {
141  bool ok;
142  QString text = QInputDialog::getText( nullptr, tr( "New style" ),
143  tr( "Style name:" ), QLineEdit::Normal,
144  QStringLiteral( "new style" ), &ok );
145  if ( !ok || text.isEmpty() )
146  return;
147 
148  bool res = mLayer->styleManager()->addStyleFromLayer( text );
149  if ( res ) // make it active!
150  {
151  mLayer->styleManager()->setCurrentStyle( text );
152  }
153  else
154  {
155  QgsDebugMsg( "Failed to add style: " + text );
156  }
157 }
158 
159 void QgsMapLayerStyleManagerWidget::removeStyle()
160 {
161  QString current = mLayer->styleManager()->currentStyle();
162  QList<QStandardItem *> items = mModel->findItems( current );
163  if ( items.isEmpty() )
164  return;
165 
166  QStandardItem *item = items.at( 0 );
167  bool res = mLayer->styleManager()->removeStyle( current );
168  if ( res )
169  {
170  mModel->removeRow( item->row() );
171  }
172  else
173  {
174  QgsDebugMsg( "Failed to remove current style" );
175  }
176 
177 }
178 
179 void QgsMapLayerStyleManagerWidget::saveAsDefault()
180 {
181  QString errorMsg;
182 
183  if ( QgsVectorLayer *layer = qobject_cast<QgsVectorLayer *>( mLayer ) )
184  {
185  if ( layer->dataProvider()->isSaveAndLoadStyleToDatabaseSupported() )
186  {
187  QMessageBox askToUser;
188  askToUser.setWindowTitle( tr( "Save Style" ) );
189  askToUser.setText( tr( "Save default style to: " ) );
190  askToUser.setIcon( QMessageBox::Question );
191  askToUser.addButton( tr( "Cancel" ), QMessageBox::RejectRole );
192  askToUser.addButton( tr( "Local database" ), QMessageBox::NoRole );
193  askToUser.addButton( tr( "Datasource database" ), QMessageBox::YesRole );
194 
195  switch ( askToUser.exec() )
196  {
197  case 0:
198  return;
199  case 2:
200  layer->saveStyleToDatabase( QLatin1String( "" ), QLatin1String( "" ), true, QLatin1String( "" ), errorMsg );
201  if ( errorMsg.isNull() )
202  {
203  return;
204  }
205  break;
206  default:
207  break;
208  }
209  }
210  }
211 
212  bool defaultSavedFlag = false;
213  errorMsg = mLayer->saveDefaultStyle( defaultSavedFlag );
214  if ( !defaultSavedFlag )
215  {
216  QMessageBox::warning( this, tr( "Default Style" ), errorMsg );
217  }
218 
219 }
220 
221 void QgsMapLayerStyleManagerWidget::loadDefault()
222 {
223  QString msg;
224  bool defaultLoadedFlag = false;
225 
226  if ( QgsVectorLayer *layer = qobject_cast<QgsVectorLayer *>( mLayer ) )
227  {
228  if ( layer->dataProvider()->isSaveAndLoadStyleToDatabaseSupported() )
229  {
230  QMessageBox askToUser;
231  askToUser.setWindowTitle( tr( "Load Style" ) );
232  askToUser.setText( tr( "Load default style from: " ) );
233  askToUser.setIcon( QMessageBox::Question );
234  askToUser.addButton( tr( "Cancel" ), QMessageBox::RejectRole );
235  askToUser.addButton( tr( "Local database" ), QMessageBox::NoRole );
236  askToUser.addButton( tr( "Datasource database" ), QMessageBox::YesRole );
237 
238  switch ( askToUser.exec() )
239  {
240  case 0:
241  return;
242  case 2:
243  msg = layer->loadNamedStyle( mLayer->styleURI(), defaultLoadedFlag );
244  if ( !defaultLoadedFlag )
245  {
246  //something went wrong - let them know why
247  QMessageBox::information( this, tr( "Default Style" ), msg );
248  }
249  if ( msg.compare( tr( "Loaded from Provider" ) ) )
250  {
251  QMessageBox::information( this, tr( "Default Style" ),
252  tr( "No default style was found for this layer" ) );
253  }
254  return;
255  default:
256  break;
257  }
258  }
259  }
260 
261  QString myMessage;
262  if ( QgsVectorLayer *layer = qobject_cast<QgsVectorLayer *>( mLayer ) )
263  {
264  myMessage = layer->loadNamedStyle( mLayer->styleURI(), defaultLoadedFlag, true );
265  }
266  if ( QgsRasterLayer *layer = qobject_cast<QgsRasterLayer *>( mLayer ) )
267  {
268  myMessage = layer->loadNamedStyle( mLayer->styleURI(), defaultLoadedFlag );
269  }
270 
271 // QString myMessage = layer->loadDefaultStyle( defaultLoadedFlag );
272  //reset if the default style was loaded OK only
273 
274 
275  if ( !defaultLoadedFlag )
276  {
277  //something went wrong - let them know why
278  QMessageBox::information( this, tr( "Default Style" ), myMessage );
279  }
280  else
281  {
282  emit widgetChanged();
283  }
284 
285 }
286 
287 void QgsMapLayerStyleManagerWidget::saveStyle()
288 {
289 
290 }
291 
292 void QgsMapLayerStyleManagerWidget::loadStyle()
293 {
294  QgsSettings myQSettings; // where we keep last used filter in persistent state
295  QString myLastUsedDir = myQSettings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
296 
297  QString myFileName = QFileDialog::getOpenFileName( this, tr( "Load layer properties from style file" ), myLastUsedDir,
298  tr( "QGIS Layer Style File" ) + " (*.qml);;" + tr( "SLD File" ) + " (*.sld)" );
299  if ( myFileName.isNull() )
300  {
301  return;
302  }
303 
304  QString myMessage;
305  bool defaultLoadedFlag = false;
306 
307  if ( myFileName.endsWith( QLatin1String( ".sld" ), Qt::CaseInsensitive ) )
308  {
309  // load from SLD
310  myMessage = mLayer->loadSldStyle( myFileName, defaultLoadedFlag );
311  }
312  else
313  {
314  myMessage = mLayer->loadNamedStyle( myFileName, defaultLoadedFlag );
315  }
316  //reset if the default style was loaded OK only
317  if ( defaultLoadedFlag )
318  {
319  emit widgetChanged();
320  }
321  else
322  {
323  //let the user know what went wrong
324  QMessageBox::warning( this, tr( "Load Style" ), myMessage );
325  }
326 
327  QFileInfo myFI( myFileName );
328  QString myPath = myFI.path();
329  myQSettings.setValue( QStringLiteral( "style/lastStyleDir" ), myPath );
330 
331 }
A panel widget that can be shown in the map style dock.
Base class for all map layer types.
Definition: qgsmaplayer.h:61
QStringList styles() const
Returns list of all defined style names.
void currentStyleChanged(const QString &currentName)
Emitted when the current style has been changed.
virtual QString loadSldStyle(const QString &uri, bool &resultFlag)
Attempts to style the layer using the formatting from an SLD type file.
void styleRenamed(const QString &oldName, const QString &newName)
Emitted when a style has been renamed.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
virtual QString loadNamedStyle(const QString &uri, bool &resultFlag)
Retrieve a named style for this layer if one exists (either as a .qml file on disk or as a record in ...
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
virtual QString styleURI() const
Retrieve the style URI for this layer (either as a .qml file on disk or as a record in the users styl...
bool isValid() const
Returns the status of the layer.
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:74
QgsMapLayerStyleManager * styleManager() const
Gets access to the layer&#39;s style manager.
void styleAdded(const QString &name)
Emitted when a new style has been added.
bool removeStyle(const QString &name)
Remove a stored style.
void styleRemoved(const QString &name)
Emitted when a style has been removed.
QgsMapLayerStyleManagerWidget(QgsMapLayer *layer, QgsMapCanvas *canvas, QWidget *parent=nullptr)
Style manager widget to manage the layers styles.
void widgetChanged()
Emitted when the widget state changes.
bool addStyleFromLayer(const QString &name)
Add style by cloning the current one.
QString currentStyle() const
Returns name of the current style.
virtual QString saveDefaultStyle(bool &resultFlag)
Save the properties of this layer as the default style (either as a .qml file on disk or as a record ...
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Represents a vector layer which manages a vector based data sets.
bool setCurrentStyle(const QString &name)
Set a different style as the current style - will apply it to the layer.