All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
LayerTreeModel.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/vp/qt/LayerTreeModel.cpp
22 
23  \brief The class that defines the model used in the Qt Model/View architecture
24 */
25 
26 // TerraLib
27 #include "../../common/STLUtils.h"
28 #include "../../common/Translator.h"
29 #include "../Exception.h"
30 #include "LayerItem.h"
31 #include "LayerTreeModel.h"
32 
33 te::vp::LayerTreeModel::LayerTreeModel(const std::list<te::map::AbstractLayerPtr>& layers, bool singleSelection, QObject * parent)
34  : QAbstractItemModel(parent),
35  m_singleSelection(singleSelection)
36 {
37  for(std::list<te::map::AbstractLayerPtr>::const_iterator it = layers.begin(); it != layers.end(); ++it)
38  {
39  te::qt::widgets::AbstractTreeItem* litem = new LayerItem(*it, 0);
40 
41  if(litem)
42  m_items.push_back(litem);
43  }
44 }
45 
47 {
48  te::common::FreeContents(m_items);
49 }
50 
51 bool te::vp::LayerTreeModel::canFetchMore(const QModelIndex& parent) const
52 {
53  if(!parent.isValid())
54  return !m_items.empty();
55 
56  te::qt::widgets::AbstractTreeItem* item = static_cast<te::qt::widgets::AbstractTreeItem*>(parent.internalPointer());
57 
58  return item->canFetchMore();
59 }
60 
61 int te::vp::LayerTreeModel::columnCount(const QModelIndex& /*parent*/) const
62 {
63  return 2;
64 }
65 
66 QVariant te::vp::LayerTreeModel::data(const QModelIndex& index, int role) const
67 {
68  if(!index.isValid())
69  return QVariant();
70 
71  te::qt::widgets::AbstractTreeItem* item = static_cast<te::qt::widgets::AbstractTreeItem*>(index.internalPointer());
72 
73  if(item == 0)
74  return QVariant();
75 
76  return item->data(index.column(), role);
77 }
78 
79 void te::vp::LayerTreeModel::fetchMore(const QModelIndex& parent)
80 {
81  if(!parent.isValid())
82  return;
83 
84  te::qt::widgets::AbstractTreeItem* item = static_cast<te::qt::widgets::AbstractTreeItem*>(parent.internalPointer());
85 
86  if(item == 0)
87  throw Exception(TE_TR("Invalid data associated to the layer model!"));
88 
89  item->fetchMore();
90 }
91 
92 Qt::ItemFlags te::vp::LayerTreeModel::flags(const QModelIndex& index) const
93 {
94  if(!index.isValid())
95  return QAbstractItemModel::flags(index) /*| Qt::ItemIsDragEnabled*/ | Qt::ItemIsDropEnabled;
96 
97  te::qt::widgets::AbstractTreeItem* item = static_cast<te::qt::widgets::AbstractTreeItem*>(index.internalPointer());
98 
99  if(item == 0)
100  throw Exception(TE_TR("Invalid data associated to the layer model!"));
101 
102  return QAbstractItemModel::flags(index) | item->flags();
103 }
104 
105 bool te::vp::LayerTreeModel::hasChildren(const QModelIndex& parent) const
106 {
107  if(!parent.isValid())
108  return !m_items.empty();
109 
110  te::qt::widgets::AbstractTreeItem* item = static_cast<te::qt::widgets::AbstractTreeItem*>(parent.internalPointer());
111 
112  if(item == 0)
113  throw Exception(TE_TR("Invalid data associated to the layer model!"));
114 
115  return item->hasChildren();
116 }
117 
118 QModelIndex te::vp::LayerTreeModel::index(int row, int column, const QModelIndex& parent) const
119 {
120  if(m_items.empty())
121  return QModelIndex();
122 
123  if(!parent.isValid() && static_cast<std::size_t>(row) >= m_items.size())
124  return QModelIndex();
125 
126  te::qt::widgets::AbstractTreeItem* parentItem = static_cast<te::qt::widgets::AbstractTreeItem*>(parent.internalPointer());
127 
128  if(parentItem && row >= parentItem->children().count())
129  return QModelIndex();
130 
131  if(!parent.isValid()) // is it a top-level item?
132  {
133 // yes!
134  te::qt::widgets::AbstractTreeItem* item = m_items[row];
135 
136  return createIndex(row, column, item);
137  }
138 
139  if(parentItem == 0)
140  throw Exception(TE_TR("Invalid data associated to the layer model!"));
141 
142  if(parentItem->children().empty())
143  throw Exception(TE_TR("The layer item in the model must have a child item!"));
144 
145  if(row >= parentItem->children().size())
146  throw Exception(TE_TR("The row for the layer item is out of range!"));
147 
148  te::qt::widgets::AbstractTreeItem* item = dynamic_cast<te::qt::widgets::AbstractTreeItem*>(parentItem->children().at(row));
149 
150  if(item == 0)
151  throw Exception(TE_TR("The layer item is not an te::qt::widgets::AbstractTreeItem!"));
152 
153  return createIndex(row, column, item);
154 }
155 
156 QModelIndex te::vp::LayerTreeModel::parent(const QModelIndex& index) const
157 {
158  if(!index.isValid())
159  return QModelIndex();
160 
161  te::qt::widgets::AbstractTreeItem* item = static_cast<te::qt::widgets::AbstractTreeItem*>(index.internalPointer());
162 
163  if(item == 0 || item->parent() == 0)
164  return QModelIndex();
165 
166  te::qt::widgets::AbstractTreeItem* parentItem = dynamic_cast<te::qt::widgets::AbstractTreeItem*>(item->parent());
167 
168  if(parentItem == 0)
169  throw Exception(TE_TR("The layer item is not an AbstractTreeItem!"));
170 
171  te::qt::widgets::AbstractTreeItem* grandParentItem = dynamic_cast<te::qt::widgets::AbstractTreeItem*>(parentItem->parent());
172 
173  if(grandParentItem == 0)
174  {
175 // the parent is a top level item
176  for(std::size_t i = 0; i != m_items.size(); ++i)
177  {
178  if(m_items[i] == parentItem)
179  return createIndex(static_cast<int>(i), index.column(), parentItem);
180  }
181  }
182  else
183  {
184 // the parent has a grandparent
185  const QObjectList& items = grandParentItem->children();
186 
187  int i = 0;
188 
189  for(QObjectList::const_iterator it = items.begin(); it != items.end(); ++it, ++i)
190  {
191  if((*it) == parentItem)
192  return createIndex(i, index.column(), parentItem);
193  }
194  }
195 
196  throw Exception(TE_TR("Could not determine the layer index in the model!"));
197 }
198 
199 int te::vp::LayerTreeModel::rowCount(const QModelIndex& parent) const
200 {
201  if(!parent.isValid()) // if parent index isnot valid we assume we are asking for root items
202  return static_cast<int>(m_items.size());
203 
204  te::qt::widgets::AbstractTreeItem* item = static_cast<te::qt::widgets::AbstractTreeItem*>(parent.internalPointer());
205 
206  if(item == 0)
207  throw Exception(TE_TR("Error: NULL layer item!"));
208 
209  return item->children().count();
210 }
211 
212 bool te::vp::LayerTreeModel::setData(const QModelIndex& index, const QVariant& value, int role)
213 {
214  if(!index.isValid())
215  return false;
216 
217  te::qt::widgets::AbstractTreeItem* item = static_cast<te::qt::widgets::AbstractTreeItem*>(index.internalPointer());
218 
219  if(item == 0)
220  return false;
221 
222  bool retval = item->setData(index.column(), value, role);
223 
224  emit dataChanged(index, index);
225 
226  if(role == Qt::CheckStateRole)
227  {
228  if(parent(index).isValid())
229  {
230 // emit the dataChanged signal for the ascendants indexes
231  QModelIndex ascendentIndex = parent(index);
232 
233  while(ascendentIndex.isValid())
234  {
235  emit dataChanged(ascendentIndex, ascendentIndex);
236  ascendentIndex = parent(ascendentIndex);
237  }
238  }
239 // if the vector processing uses only one input layer
240  if(m_singleSelection)
241  {
242 // Verify if the selectd item is layer or property. If property, the return of "getLayer" is 0.
243  if(item->getLayer() != 0)
244  {
245 // Unselect all layers different than "item"
246  for(size_t i = 0; i < m_items.size(); ++i)
247  {
248  if(m_items[i] == item)
249  continue;
250 
251  LayerItem* litem = dynamic_cast<LayerItem*>(m_items[i]);
252  litem->isSelected(false);
253  }
254  }
255  }
256  }
257 
258 // after all changes is necessary to emit the dataChenged signal to refresh the checkboxes.
259  QModelIndex start_ix = createIndex( 0, 0 );
260  QModelIndex end_ix = createIndex( 0, 1 );
261  emit( dataChanged( start_ix, end_ix ) );
262 
263  return retval;
264 }
265 
266 QVariant te::vp::LayerTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
267 {
268  if(role == Qt::DisplayRole)
269  {
270  if(orientation == Qt::Horizontal)
271  {
272  if(section == 0)
273  return QVariant(TE_TR("Layers"));
274  else if(section == 1)
275  return QVariant(TE_TR("Only Selected"));
276  }
277  }
278 
279  return QAbstractItemModel::headerData(section, orientation, role);
280 }
281 
282 std::map<te::map::AbstractLayerPtr, std::vector<te::dt::Property*> > te::vp::LayerTreeModel::getSelected()
283 {
284  std::map<te::map::AbstractLayerPtr, std::vector<te::dt::Property*> > selected;
285 
286  for(size_t i = 0; i < m_items.size(); ++i)
287  {
288  LayerItem* litem = dynamic_cast<LayerItem*>(m_items[i]);
289 
290  if(litem->isSelected())
291  {
292  selected[litem->getLayer()] = litem->getSelected();
293  }
294  }
295 
296  return selected;
297 }
298 
299 void te::vp::LayerTreeModel::setLayerList(const std::list<te::map::AbstractLayerPtr>& layers)
300 {
301  //if(layers.empty())
302  //return;
303 
304  m_items.clear();
305 
306  for(std::list<te::map::AbstractLayerPtr>::const_iterator it = layers.begin(); it != layers.end(); ++it)
307  {
308  te::qt::widgets::AbstractTreeItem* litem = new LayerItem(*it, 0);
309 
310  if(litem)
311  m_items.push_back(litem);
312  }
313 
314  // after all changes is necessary to emit the dataChenged signal to refresh the checkboxes.
315  QModelIndex start_ix = createIndex( 0, 0 );
316  QModelIndex end_ix = createIndex( 0, 1 );
317  emit( dataChanged( start_ix, end_ix ) );
318 }
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
It returns the index of the item in the model specified by the given row, column and parent index...
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const
Returns the data for the given role and section in the header with the specified orientation.
int columnCount(const QModelIndex &parent=QModelIndex()) const
It returns the number of columns for the children of the given parent.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
It returns the data stored under the given role for the item referred to by the index.
bool canFetchMore(const QModelIndex &parent) const
It fetches more data for parent.
void isSelected(bool selected)
Set the Layer as selected.
Definition: LayerItem.cpp:195
int rowCount(const QModelIndex &parent=QModelIndex()) const
It returns the number of rows of the given parent.
The class that represents an item in a LayerTreeModel.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:347
LayerTreeModel(const std::list< te::map::AbstractLayerPtr > &layers, bool singleSelection=false, QObject *parent=0)
It constructs an item model with the given parent.
virtual te::map::AbstractLayerPtr getLayer() const =0
std::vector< te::qt::widgets::AbstractTreeItem * > m_items
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole)
It sets the role data for the item at index to value.
std::vector< te::dt::Property * > getSelected()
Get the selected Properties of the Layer.
Definition: LayerItem.cpp:205
The class that defines the model used in the Qt Model/View architecture.
virtual bool setData(int column, const QVariant &value, int role=Qt::EditRole)=0
bool hasChildren(const QModelIndex &parent=QModelIndex()) const
It checks if the given index has children.
Qt::ItemFlags flags(const QModelIndex &index) const
It returns the item flags for the given index.
virtual QVariant data(int column, int role) const =0
te::map::AbstractLayerPtr getLayer() const
Definition: LayerItem.cpp:190
virtual bool canFetchMore() const =0
virtual Qt::ItemFlags flags() const =0
std::map< te::map::AbstractLayerPtr, std::vector< te::dt::Property * > > getSelected()
It get the Layer selected and the Properties selected of the Layer.
A class that represents a Layer in a LayerTreeModel.
void fetchMore(const QModelIndex &parent)
It fetches any available data for the items with the parent specified by the parent index...
virtual bool hasChildren() const =0
QModelIndex parent(const QModelIndex &index) const
It returns the item parent of the given index, or QModelIndex(), if it has no parent.
void FreeContents(boost::unordered_map< K, V * > &m)
This function can be applied to a map of pointers. It will delete each pointer in the map...
Definition: BoostUtils.h:55
void setLayerList(const std::list< te::map::AbstractLayerPtr > &layers)