StyleControllerWidget.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/qt/widgets/se/StyleControllerWidget.cpp
22 
23  \brief A widget used to controll the style se element.
24 */
25 
26 // TerraLib
27 #include "StyleControllerWidget.h"
28 #include "../../../core/filesystem/FileSystem.h"
29 #include "../../../dataaccess/utils/Utils.h"
30 #include "../../../geometry/GeometryProperty.h"
31 #include "../../../fe.h"
32 #include "../../../se/FeatureTypeStyle.h"
33 #include "../../../se/Font.h"
34 #include "../../../se/Rule.h"
35 #include "../../../se/TextSymbolizer.h"
36 #include "../../../se/Utils.h"
37 #include "../../../se/Style.h"
38 #include "../../../se/Symbolizer.h"
39 #include "../../../se/serialization/xml/Style.h"
40 #include "../../../xml/AbstractWriter.h"
41 #include "../../../xml/AbstractWriterFactory.h"
42 #include "../../../xml/Reader.h"
43 #include "../../../xml/ReaderFactory.h"
44 #include "../../widgets/Utils.h"
45 #include "StyleExplorer.h"
46 #include "Symbol.h"
47 #include "SymbolPreviewWidget.h"
48 #include "SymbolSelectorDialog.h"
49 
50 // TerraLib - UIC
51 #include "ui_StyleControllerWidgetForm.h"
52 
53 // Qt
54 #include <QMessageBox>
55 #include <QFileDialog>
56 #include <QFile>
57 #include <QDir>
58 #include <QString>
59 
60 // STL
61 #include <cassert>
62 #include <fstream>
63 
64 // Boost
65 #include <boost/filesystem/operations.hpp>
66 
68  : QWidget(parent, f),
69  m_ui(new Ui::StyleControllerWidgetForm),
70  m_currentStyle(nullptr),
71  m_currentLayer(nullptr)
72 {
73  m_ui->setupUi(this);
74 
75  // Signals & slots
76  connect(m_ui->m_explorer_frame->m_iconSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(changeLegendIconSize(int)));
77  connect(m_ui->m_explorer_frame->m_addRuleToolButton, SIGNAL(clicked()), this, SLOT(onAddRuleClicked()));
78  connect(m_ui->m_explorer_frame->m_removeRuleToolButton, SIGNAL(clicked()), this, SLOT(onRemoveRuleClicked()));
79  connect(m_ui->m_explorer_frame->m_addTextSymbToolButton, SIGNAL(clicked()), this, SLOT(onAddTextSymbolizerClicked()));
80  connect(m_ui->m_explorer_frame->m_addSymbToolButton, SIGNAL(clicked()), this, SLOT(onAddSymbolizerClicked()));
81  connect(m_ui->m_explorer_frame->m_removeSymbToolButton, SIGNAL(clicked()), this, SLOT(onRemoveSymbolizerClicked()));
82  connect(m_ui->m_explorer_frame->m_upSymbToolButton, SIGNAL(clicked()), this, SLOT(onUpSymbolizerClicked()));
83  connect(m_ui->m_explorer_frame->m_downSymbToolButton, SIGNAL(clicked()), this, SLOT(onDownSymbolizerClicked()));
84  connect(m_ui->m_explorer_frame->m_libManagerToolButton, SIGNAL(clicked()), this, SLOT(onLibraryManagerClicked()));
85  connect(m_ui->m_explorer_frame->m_exportStyleToolButton, SIGNAL(clicked()), this, SLOT(onExportClicked()));
86  connect(m_ui->m_explorer_frame->m_importStyleToolButton, SIGNAL(clicked()), this, SLOT(onImportClicked()));
87  connect(m_ui->m_explorer_frame->m_mapRefreshToolButton, SIGNAL(clicked()), this, SLOT(onMapRefreshClicked()));
88  connect(m_ui->m_visualStyleRadioButton, SIGNAL(clicked(bool)), SLOT(onVisualStyleChecked(bool)));
89  connect(m_ui->m_selectionStyleRadioButton, SIGNAL(clicked(bool)), SLOT(onSelectionStyleChecked(bool)));
90 
91  m_ui->m_explorer_frame->m_addRuleToolButton->setEnabled(false);
92  m_ui->m_explorer_frame->m_removeRuleToolButton->setEnabled(false);
93 }
94 
96 
98 {
99  m_currentStyle = style;
100  m_currentLayer = nullptr;
101 
102  m_ui->m_explorer->setStyle(style);
103 
104  m_ui->m_visualStyleRadioButton->setEnabled(false);
105  m_ui->m_selectionStyleRadioButton->setEnabled(false);
106 
107  m_ui->m_layerGroupBox->setVisible(false);
108 }
109 
111 {
112  m_currentLayer = layer;
113 
114  if (!layer->getSelectionStyle())
115  {
116  std::unique_ptr<te::da::DataSetType> dsType = layer->getSchema();
117 
118  if (dsType->hasGeom())
119  {
121 
122  te::se::Symbolizer* symbolizer = te::se::CreateSymbolizer(gp->getGeometryType(), selColor);
123 
124  te::se::Rule* rule = new te::se::Rule;
125 
126  if (symbolizer != nullptr)
127  rule->push_back(symbolizer);
128 
130  style->push_back(rule);
131 
132  layer->setSelectionStyle(style);
133 
134  m_ui->m_selectionStyleRadioButton->setEnabled(true);
135  }
136  else
137  {
138  m_ui->m_visualStyleRadioButton->setChecked(true);
139  m_ui->m_selectionStyleRadioButton->setEnabled(false);
140  }
141  }
142  else
143  {
144  m_ui->m_selectionStyleRadioButton->setEnabled(true);
145  }
146 
147  if (m_ui->m_visualStyleRadioButton->isChecked())
148  {
149  m_ui->m_explorer->setStyle(layer->getStyle(), currentRule);
150 
151  m_currentStyle = layer->getStyle();
152  }
153  else
154  {
155  m_ui->m_explorer->setStyle(layer->getSelectionStyle(), currentRule);
156 
158  }
159 
160 }
161 
163 {
164  return m_ui->m_explorer;
165 }
166 
168 {
169  if (!m_currentLayer)
170  {
171  QMessageBox::information(this, tr("Style"), tr("Select a layer first."));
172  return;
173  }
174 
175  if (!m_currentStyle)
176  {
177  QMessageBox::information(this, tr("Style"), tr("Style not defined"));
178  return;
179  }
180 
181  //std::unique_ptr<te::da::DataSetType> schema(m_currentLayer->getSchema());
182 
183  //te::gm::GeometryProperty* geometryProperty = te::da::GetFirstGeomProperty(schema.get());
184 
185  //te::se::Rule* rule = new te::se::Rule;
186 
187  //std::string* ruleName = new std::string("SUDESTE");
188 
189  //rule->setName(ruleName);
190 
191  //te::fe::PropertyName* propName = new te::fe::PropertyName("NM_REGIAO");
192  //te::fe::Literal* propValue = new te::fe::Literal("SUDESTE");
193  //te::fe::PropertyIsEqualTo* equal = new te::fe::PropertyIsEqualTo(propName, propValue);
194  //te::fe::Filter* filter = new te::fe::Filter();
195  //filter->setOp(equal);
196 
197  //rule->setFilter(filter);
198 
199  //te::se::Symbolizer* symbolizer = te::se::CreateSymbolizer(geometryProperty->getGeometryType());
200 
201 
202  //if (symbolizer)
203  // rule->push_back(symbolizer);
204 
205  te::se::Rule* rule = nullptr; // the new rule must be created by another component
206 
207  m_currentStyle->push_back(rule);
208 
209  m_ui->m_explorer->updateStyleTree();
210 
211  emit updateLayer();
212 }
213 
215 {
216  if (!m_currentStyle)
217  {
218  QMessageBox::information(this, tr("Style"), tr("Style not defined"));
219  return;
220  }
221 
222  if (m_currentStyle->getRules().size() == 1)
223  {
224  QMessageBox::information(this, tr("Style"), tr("It is not possible to leave a style without rules."));
225  return;
226  }
227 
228  te::se::Rule* rule = m_ui->m_explorer->getCurrentRule();
229 
230  if (rule == nullptr)
231  {
232  QMessageBox::information(this, tr("Style"), tr("Select a rule first."));
233  return;
234  }
235 
236  for (std::size_t t = 0; t < m_currentStyle->getRules().size(); ++t)
237  {
238  if (m_currentStyle->getRule(t) == rule)
239  {
241  break;
242  }
243  }
244 
245  m_ui->m_explorer->updateStyleTree();
246 
247  emit updateLayer();
248 }
249 
251 {
252  te::se::Rule* rule = m_ui->m_explorer->getCurrentRule();
253 
254  if (rule == nullptr)
255  {
256  QMessageBox::information(this, tr("Style"), tr("Select a rule first."));
257  return;
258  }
259 
260  //creates new text symbolizer representation
261  te::se::Fill* fill = te::se::CreateFill("#000000", "1.0");
263  te::se::Symbolizer* symb = te::se::CreateTextSymbolizer("", fill, font);
264 
265  rule->push_back(symb);
266 
267  m_ui->m_explorer->updateStyleTree();
268 }
269 
271 {
272  te::se::Rule* rule = m_ui->m_explorer->getCurrentRule();
273 
274  if(rule == nullptr)
275  {
276  QMessageBox::information(this, tr("Style"), tr("Select a rule first."));
277  return;
278  }
279 
280  te::se::Symbolizer* symb = m_ui->m_explorer->getCurrentSymbolizer();
281 
282  if(symb)
283  rule->push_back(symb->clone());
284  else
285  {
286  assert(!rule->getSymbolizers().empty());
287 
288  const te::se::Symbolizer* symb = rule->getSymbolizer(0);
289  assert(symb);
290 
291  rule->push_back(symb->clone());
292  }
293 
294  m_ui->m_explorer->updateStyleTree();
295 }
296 
298 {
299  te::se::Symbolizer* symb = m_ui->m_explorer->getCurrentSymbolizer();
300 
301  if(symb == nullptr)
302  {
303  QMessageBox::information(this, tr("Style"), tr("Select a symbol first."));
304  return;
305  }
306 
307  te::se::Rule* rule = m_ui->m_explorer->getCurrentRule();
308  assert(rule);
309 
310  if(rule->getSymbolizers().size() == 1)
311  {
312  QMessageBox::information(this, tr("Style"), tr("The rule must have at least one symbol."));
313  return;
314  }
315 
316  for(std::size_t i = 0; i < rule->getSymbolizers().size(); ++i)
317  {
318  if(rule->getSymbolizer(i) == symb)
319  {
320  rule->removeSymbolizer(i);
321  break;
322  }
323  }
324 
325  m_ui->m_explorer->updateStyleTree();
326 }
327 
329 {
330  te::se::Symbolizer* symb = m_ui->m_explorer->getCurrentSymbolizer();
331 
332  if(symb == nullptr)
333  {
334  QMessageBox::information(this, tr("Style"), tr("Select a symbol first."));
335  return;
336  }
337 
338  m_ui->m_explorer->goUpSymbolizer();
339 }
340 
342 {
343  te::se::Symbolizer* symb = m_ui->m_explorer->getCurrentSymbolizer();
344 
345  if(symb == nullptr)
346  {
347  QMessageBox::information(this, tr("Style"), tr("Select a symbol first."));
348  return;
349  }
350 
351  m_ui->m_explorer->goDownSymbolizer();
352 }
353 
355 {
356  te::se::Rule* rule = m_ui->m_explorer->getCurrentRule();
357 
358  if(!rule)
359  {
360  QMessageBox::information(this, tr("Style"), tr("Select a rule first."));
361  return;
362  }
363 
364  Symbol* symbol = te::qt::widgets::SymbolSelectorDialog::getSymbol(this, tr("Symbol Selector"));
365  if(symbol == nullptr)
366  return;
367 
368  std::vector<te::se::Symbolizer*> symbolizers;
369  for(std::size_t i = 0; i < symbol->getSymbolizersCount(); ++i)
370  symbolizers.push_back(symbol->getSymbolizer(i)->clone());
371 
372  rule->setSymbolizers(symbolizers);
373 
374  m_ui->m_explorer->updateStyleTree();
375 }
376 
378 {
379  if (!m_currentStyle)
380  {
381  QMessageBox::information(this, tr("Style"), tr("Select a layer first."));
382  return;
383  }
384 
385  QString styleFile = QFileDialog::getSaveFileName(this, tr("Save File"), te::qt::widgets::GetFilePathFromSettings("style"), "Style file (*.sld)");
386 
387  if (styleFile.isEmpty())
388  return;
389 
390  QFileInfo info(styleFile);
391 
392  te::qt::widgets::AddFilePathToSettings(info.absolutePath(), "style");
393 
394  if (info.suffix().isEmpty())
395  styleFile.append(".sld");
396 
397  writeStyle(m_currentStyle, styleFile.toUtf8().data());
398 }
399 
401 {
402  if (!m_currentLayer)
403  {
404  QMessageBox::information(this, tr("Style"), tr("Select a layer first."));
405  return;
406  }
407 
408  QString styleFile = QFileDialog::getOpenFileName(this, tr("Select a style file"), te::qt::widgets::GetFilePathFromSettings("style"), "Style file (*.sld)");
409 
410  QFileInfo info(styleFile);
411 
412  te::qt::widgets::AddFilePathToSettings(info.absolutePath(), "style");
413 
414  if (!styleFile.isEmpty())
415  readStyle(styleFile.toUtf8().data());
416  else
417  return;
418 }
419 
421 {
422  emit mapRefresh();
423 }
424 
426 {
427  m_ui->m_explorer->setLegendIconSize(size);
428 }
429 
431 {
432  if (state && m_currentLayer && m_currentLayer->getStyle())
433  {
434  m_ui->m_explorer->setStyle(m_currentLayer->getStyle());
436  }
437 }
438 
440 {
442  {
443  m_ui->m_explorer->setStyle(m_currentLayer->getSelectionStyle());
445  }
446 }
447 
449 {
450  boost::filesystem::wpath file = te::core::FileSystem::absolutePath(path);
451 
452  {
453  std::unique_ptr<te::xml::AbstractWriter> writer(te::xml::AbstractWriterFactory::make());
454 
455  writer->setURI(file.string());
456  writer->writeStartDocument("UTF-8", "no");
457 
458  writer->writeStartElement("StyledLayerDescriptor");
459 
460  writer->writeAttribute("xmlns", "http://www.opengis.net/sld");
461  writer->writeAttribute("xmlns:ogc", "http://www.opengis.net/ogc");
462  writer->writeAttribute("xmlns:se", "http://www.opengis.net/se");
463  writer->writeAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
464  writer->writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
465  writer->writeAttribute("xsi:schemaLocation", "http://www.opengis.net/sld StyledLayerDescriptor.xsd");
466 
467  writer->writeAttribute("version", style->getVersion());
468 
469  writer->writeStartElement("NamedLayer");
470  writer->writeStartElement("UserStyle");
471 
472  te::se::serialize::Style::getInstance().write(style, *writer.get());
473 
474  writer->writeEndElement("UserStyle");
475  writer->writeEndElement("NamedLayer");
476 
477  writer->writeEndElement("StyledLayerDescriptor");
478  writer->writeToFile();
479  }
480 }
481 
483 {
484  std::unique_ptr<te::se::Style> style;
485 
486  boost::filesystem::wpath file = te::core::FileSystem::absolutePath(path);
487  {
488  std::unique_ptr<te::xml::Reader> reader(te::xml::ReaderFactory::make());
489  reader->setValidationScheme(false);
490 
491  reader->read(file.string());
492  reader->next();
493 
494  if (!checkSymbolizer(file.string()))
495  {
496  QMessageBox::warning(this, tr("Style Explorer"), tr("The selected theme is not compatible with the current data."));
497  return;
498  }
499 
500  if ((reader->getNodeType() == te::xml::START_ELEMENT) &&
501  (reader->getElementLocalName() == "StyledLayerDescriptor"))
502  reader->next();
503 
504  if ((reader->getNodeType() == te::xml::START_ELEMENT) &&
505  (reader->getElementLocalName() == "NamedLayer"))
506  reader->next();
507 
508  if ((reader->getNodeType() == te::xml::START_ELEMENT) &&
509  (reader->getElementLocalName() == "Name"))
510  {
511  reader->next();
512 
513  if(reader->getNodeType() == te::xml::VALUE)
514  reader->next();
515 
516  if(reader->getNodeType() == te::xml::END_ELEMENT)
517  reader->next();
518  }
519 
520  if ((reader->getNodeType() == te::xml::START_ELEMENT) &&
521  (reader->getElementLocalName() == "UserStyle"))
522  reader->next();
523 
524  if ((reader->getNodeType() == te::xml::START_ELEMENT) &&
525  (reader->getElementLocalName() == "Name"))
526  {
527  reader->next();
528 
529  if(reader->getNodeType() == te::xml::VALUE)
530  reader->next();
531 
532  if(reader->getNodeType() == te::xml::END_ELEMENT)
533  reader->next();
534  }
535 
536  if ((reader->getNodeType() == te::xml::START_ELEMENT) &&
537  (reader->getElementLocalName() == "FeatureTypeStyle"))
538  {
539  if (reader->getNodeType() == te::xml::START_ELEMENT)
540  style.reset(te::se::serialize::Style::getInstance().read(*reader.get()));
541 
542  m_ui->m_explorer->importStyle(style.release(), m_ui->m_visualStyleRadioButton->isChecked());
543  }
544  else
545  {
546  QMessageBox::warning(this, tr("Style Explorer"), tr("The style contained unrecognized elements and could not be read."));
547  return;
548  }
549  }
550 }
551 
553 {
554  m_currentStyle = nullptr;
555  m_currentLayer = nullptr;
556 
557  m_ui->m_explorer->setStyle(nullptr);
558 
559  m_ui->m_visualStyleRadioButton->setEnabled(false);
560  m_ui->m_selectionStyleRadioButton->setEnabled(false);
561 
562  m_ui->m_layerGroupBox->setVisible(false);
563 }
564 
566 {
567  std::string sldFile;
568  std::ifstream t(file);
569  std::stringstream buffer;
570  buffer << t.rdbuf();
571 
572  sldFile = buffer.str();
573 
574  std::size_t found = sldFile.find(m_ui->m_explorer->getCurrentSymbolizer()->getType());
575 
576  if (found != std::string::npos)
577  return true;
578  else
579  return false;
580 }
te::se::Symbolizer * getSymbolizer(const std::size_t &i) const
It returns the n-th Symbolizer.
Definition: Symbol.cpp:63
Geometric property.
The Style defines the styling that is to be applied to a geographic dataset (vector geometries or cov...
Definition: Style.h:65
This is the base class for layers.
Definition: AbstractLayer.h:77
A widget used to preview symbol elements.
TESEEXPORT Symbolizer * CreateSymbolizer(const te::gm::GeomType &geomType)
Try creates an appropriate symbolizer based on given geometry type.
This class represents a symbol.
void setLayer(te::map::AbstractLayer *layer, std::string selColor, te::se::Rule *currentRule)
std::size_t getSymbolizersCount() const
It returns the number of Symbolizers that compose of the symbol.
Definition: Symbol.cpp:58
virtual te::se::Style * getSelectionStyle() const
It returns the selection Style associated to the layer.
std::unique_ptr< Ui::StyleControllerWidgetForm > m_ui
Widget form.
A widget used to explore a style.
A Symbolizer describes how a feature is to appear on a map.
Definition: Symbolizer.h:80
TEQTWIDGETSEXPORT void AddFilePathToSettings(const QString &path, const QString &typeFile)
Save last used path in QSettings.
static te::xml::AbstractWriter * make()
It creates a new XML writer using the dafault implementation.
void push_back(const std::string &semanticTypeIdentifier)
Definition: Style.cpp:75
static te::xml::Reader * make()
It creates a new XML reader using the dafault implementation.
TESEEXPORT TextSymbolizer * CreateTextSymbolizer(const std::string &label, Fill *fill, Font *font)
Creates a text symbolizer.
void push_back(Symbolizer *s)
Definition: Rule.cpp:138
void writeStyle(const te::se::Style *style, std::string path)
A dialog used to select a specific symbol.
Rule * getRule(std::size_t i) const
Definition: Style.cpp:105
const std::vector< Rule * > & getRules() const
Definition: Style.cpp:94
A widget used to explore a style.
static std::string absolutePath(const std::string &path)
Retrives the absolute path for the given path in UTF-8.
Definition: FileSystem.cpp:76
Symbol * getSymbol() const
Gets the selected symbol.
te::map::AbstractLayer * m_currentLayer
Current Layer pointer (used for raster symbolizer information)
StyleControllerWidget(QWidget *parent=0, Qt::WindowFlags f=0)
Constructs a StyleControllerWidget which is a child of parent, with widget flags set to f...
static Style & getInstance()
It returns a reference to the singleton instance.
The FeatureTypeStyle defines the styling that is to be applied to a dataset that can be viewed as a f...
A widget used to controll the style se element.
virtual te::se::Style * getStyle() const
It returns the Style associated to the layer.
virtual std::unique_ptr< LayerSchema > getSchema() const =0
It returns the layer schema.
GeomType getGeometryType() const
It returns the geometry subtype allowed for the property.
A Font specifies the text font to use in a text symbolizer.
Definition: Font.h:63
A Fill specifies the pattern for filling an area geometry.
Definition: Fill.h:59
This class represents a symbol. TODO: More description!
Definition: Symbol.h:54
void removeRule(std::size_t i)
Definition: Style.cpp:111
virtual void setSelectionStyle(te::se::Style *style)
It sets the selection Style associated to the layer.
void setSymbolizers(const std::vector< Symbolizer * > &symbs)
Definition: Rule.cpp:152
const std::vector< Symbolizer * > & getSymbolizers() const
Definition: Rule.cpp:158
void removeSymbolizer(std::size_t i)
Definition: Rule.cpp:169
void setStyle(te::se::Style *style)
Sets a style element to this widget.
A Rule is used to attach property/scale conditions to and group the individual symbols used for rende...
Definition: Rule.h:76
TESEEXPORT Font * CreateFont(const std::string &family, const std::string &size, const te::se::Font::FontStyleType &style=te::se::Font::StyleNormal, const te::se::Font::FontWeightType &weight=te::se::Font::WeightNormal)
Creates a font.
TEQTWIDGETSEXPORT QString GetFilePathFromSettings(const QString &typeFile)
Returns the value of the last saved file path for the typeFile required.
virtual Symbolizer * clone() const =0
It creates a new copy of this object.
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
te::se::Style * m_currentStyle
current style.
const Symbolizer * getSymbolizer(std::size_t i) const
Definition: Rule.cpp:163
file(WRITE ${CMAKE_BINARY_DIR}/config_qhelp.cmake"configure_file (${TERRALIB_ABSOLUTE_ROOT_DIR}/doc/qhelp/help.qhcp.in ${CMAKE_BINARY_DIR}/share/terraview/help/help.qhcp @ONLY)") add_custom_command(OUTPUT del_dir COMMAND $
TESEEXPORT Fill * CreateFill(const std::string &color, const std::string &opacity)
Creates a fill.
const std::string & getVersion() const
Definition: Style.cpp:148