All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
DataSetTableModel.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2011-2012 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/table/DataSetTableModel.cpp
22 
23  \brief A model based on te::da::DataSet.
24 */
25 
26 // TerraLib
27 #include "../../../common/Exception.h"
28 #include "../../../dataaccess/dataset/DataSet.h"
29 #include "../../../dataaccess/dataset/ObjectIdSet.h"
30 #include "../../../dataaccess/utils/Utils.h"
31 #include "../../../datatype/Enums.h"
32 #include "../../../datatype/SimpleData.h"
33 #include "../../../memory/DataSet.h"
34 #include "../../../memory/DataSetItem.h"
35 #include "../Utils.h"
36 #include "DataSetTableModel.h"
37 #include "Promoter.h"
38 
39 // Qt
40 #include <QIcon>
41 #include <QMessageBox>
42 
43 bool IsPkey(const int& column, const std::vector<size_t>& pkeys)
44 {
45  std::vector<size_t>::const_iterator it;
46 
47  for(it=pkeys.begin(); it!=pkeys.end(); ++it)
48  if(*it == column)
49  return true;
50 
51  return false;
52 }
53 
54 QString ColumnType(const int& type)
55 {
56 
57  switch(type)
58  {
59  case te::dt::VOID_TYPE:
60  return QObject::tr("Void");
61  break;
62 
63  case te::dt::BIT_TYPE:
64  return QObject::tr("Bit");
65  break;
66 
67  case te::dt::CHAR_TYPE:
68  return QObject::tr("Char");
69  break;
70 
71  case te::dt::UCHAR_TYPE:
72  return QObject::tr("Unsigned char");
73  break;
74 
75  case te::dt::INT16_TYPE:
76  case te::dt::INT32_TYPE:
77  case te::dt::INT64_TYPE:
78  return QObject::tr("Integer");
79  break;
80 
84  return QObject::tr("Unsigned integer");
85  break;
86 
88  return QObject::tr("Boolean");
89  break;
90 
91  case te::dt::FLOAT_TYPE:
92  return QObject::tr("Float");
93  break;
94 
96  return QObject::tr("Double");
97  break;
98 
100  return QObject::tr("Numeric");
101  break;
102 
103  case te::dt::STRING_TYPE:
104  return QObject::tr("String");
105  break;
106 
108  return QObject::tr("Byte array");
109  break;
110 
112  return QObject::tr("Geometry");
113  break;
114 
116  return QObject::tr("Date time");
117  break;
118 
119  default:
120  return QObject::tr("Unknown");
121  break;
122  }
123 }
124 
125 class Editor
126 {
127  public:
129  {
130 
131  }
132 
133  void clear()
134  {
135  m_editions.clear();
136  }
137 
138  void setValue(const int& row, const int& column, const std::string& value)
139  {
140  std::pair<int, int> key(row, column);
141  m_editions[key] = value;
142  }
143 
144  bool isEdited(const int& row, const int& column) const
145  {
146  return m_editions.find(std::pair<int, int>(row, column)) != m_editions.end();
147  }
148 
149  std::string getValue(const int& row, const int& column)
150  {
151  return m_editions[std::pair<int, int>(row, column)];
152  }
153 
154  bool hasEditions() const
155  {
156  return !m_editions.empty();
157  }
158 
159  void getEditedDataSet(te::da::DataSet* in, te::mem::DataSet* out, std::vector< std::set<int> >& fields)
160  {
161  std::vector<int> rows;
162 
163  fields = getEditedLists(rows);
164 
165  // Creating the items
166  for(int i = 0; i < (int)rows.size(); ++i)
167  {
169  std::set<int> ef = fields[i];
170 
171  in->move(rows[i]);
172 
173  // For each property
174  for(int j = 0; j < (int) in->getNumProperties(); ++j)
175  {
176  bool edited = ef.find(j) != ef.end();
177 
178  if(!edited)
179  item->setValue(j, (in->isNull(j)) ? 0 : in->getValue(j).release());
180  else
181  {
182  std::string data = getValue(rows[i], j);
183 
184  switch(in->getPropertyDataType(j))
185  {
186  case te::dt::INT16_TYPE:
187  item->setValue(j, new te::dt::Int16(atoi(data.c_str())));
188  break;
189 
190  case te::dt::INT32_TYPE:
191  item->setValue(j, new te::dt::Int32(atoi(data.c_str())));
192  break;
193 
194  case te::dt::INT64_TYPE:
195  item->setValue(j, new te::dt::Int64(atoi(data.c_str())));
196  break;
197 
198  case te::dt::FLOAT_TYPE:
199  item->setValue(j, new te::dt::Float(atof(data.c_str())));
200  break;
201 
202  case te::dt::DOUBLE_TYPE:
203  item->setValue(j, new te::dt::Double(atof(data.c_str())));
204  break;
205 
207  item->setValue(j, new te::dt::Numeric(data));
208  break;
209 
210  case te::dt::STRING_TYPE:
211  item->setValue(j, new te::dt::String(data));
212  break;
213 
214  default:
215  break;
216  }
217  }
218  }
219 
220  out->add(item);
221  }
222  }
223 
224  void columnsRemoved(const int& init, const int& final)
225  {
226  for(int i = init; i <= final; i++)
227  columnRemoved(i);
228  }
229 
230  void columnRemoved(const int& column)
231  {
232  std::map< std::pair<int, int>, std::string > aux;
233  std::map< std::pair<int, int>, std::string >::iterator it;
234 
235  for(it = m_editions.begin(); it != m_editions.end(); ++it)
236  {
237  int cE = it->first.second;
238 
239  if(cE == column)
240  continue;
241 
242  std::pair<int, int> rC = it->first;
243 
244  if(rC.second > column)
245  rC.second--;
246 
247  aux[rC] = it->second;
248  }
249 
250  m_editions = aux;
251  }
252 
253  protected:
254 
255  std::vector< std::set<int> > getEditedLists(std::vector<int>& rows)
256  {
257  std::vector< std::set<int> > res;
258 
259  if(!m_editions.empty())
260  {
261  std::set<int> subRes;
262  int current = m_editions.begin()->first.first;
263  rows.push_back(current);
264  std::map< std::pair<int, int>, std::string >::iterator it;
265 
266  for(it=m_editions.begin(); it!= m_editions.end(); ++it)
267  {
268  int cR = it->first.first;
269 
270  if(cR != current)
271  {
272  rows.push_back(cR);
273  res.push_back(subRes);
274  subRes.clear();
275  current = cR;
276  }
277 
278  subRes.insert(it->first.second);
279  }
280 
281  if(rows.size() != res.size())
282  res.push_back(subRes);
283  }
284 
285  return res;
286  }
287 
288  std::map< std::pair<int, int>, std::string > m_editions;
289 };
290 
292  : QAbstractTableModel(parent),
293  m_dataset(0),
294  m_currentRow(-1),
295  m_OIdsVisible(true),
296  m_enabled(true),
297  m_rowCount(0)
298 {
299  m_promoter = new Promoter;
300  m_editor.reset(new Editor);
301 }
302 
304 {
305  delete m_dataset;
306  delete m_promoter;
307 }
308 
310 {
311  beginResetModel();
312 
313  delete m_dataset;
314 
315  m_dataset = dset;
316 
317  if(clearEditor)
318  m_editor->clear();
319 
320  m_rowCount = (m_dataset == 0 || !m_enabled) ? 0 : (int)m_dataset->size();
321 
322  endResetModel();
323 }
324 
325 void te::qt::widgets::DataSetTableModel::setPkeysColumns(const std::vector<size_t>& pkeys)
326 {
327  m_pkeysColumns = pkeys;
328 }
329 
331 {
332  beginResetModel();
333 
334  m_promoter->promote(oids);
335 
336  endResetModel();
337 }
338 
340 {
341  return m_promoter;
342 }
343 
345 {
346  m_OIdsVisible = visible;
347 }
348 
350 {
352 
353  // Mounting oidset
354  std::vector<size_t>::iterator it;
355 
356  for(it=m_pkeysColumns.begin(); it!=m_pkeysColumns.end(); ++it)
357  oids->addProperty(m_dataset->getPropertyName(*it), *it, m_dataset->getPropertyDataType(*it));
358 
359  // Loading oid set.
360  int row;
361 
362  for(int i=initRow; i<=finalRow; i++)
363  {
364  row = (int)m_promoter->getLogicalRow(i);
365  m_dataset->move(row);
366 
367  oids->add(te::da::GenerateOID(m_dataset, oids->getPropertyNames()));
368  }
369 
370  return oids;
371 }
372 
374 {
375  beginResetModel();
376 
377  m_enabled = enabled;
378 
379  m_rowCount = (m_enabled && m_dataset != 0) ? (int)m_dataset->size() : 0;
380 
381  endResetModel();
382 }
383 
385 {
386  m_isEditable = editable;
387 }
388 
389 std::auto_ptr<te::da::DataSet> te::qt::widgets::DataSetTableModel::getEditions(const te::da::DataSetType *type, std::vector< std::set<int> > &ps)
390 {
391  std::auto_ptr<te::da::DataSet> dset;
392  te::mem::DataSet* md = new te::mem::DataSet(type);
393 
394  m_editor->getEditedDataSet(m_dataset, md, ps);
395 
396  dset.reset(md);
397 
398  return dset;
399 }
400 
402 {
403  return m_editor->hasEditions();
404 }
405 
407 {
408  m_editor->clear();
409 }
410 
411 int te::qt::widgets::DataSetTableModel::rowCount(const QModelIndex & parent) const
412 {
413  return m_rowCount;
414 }
415 
416 int te::qt::widgets::DataSetTableModel::columnCount(const QModelIndex & parent) const
417 {
418  return (m_dataset == 0) ? 0 : (int) m_dataset->getNumProperties();
419 }
420 
421 QVariant te::qt::widgets::DataSetTableModel::data(const QModelIndex & index, int role) const
422 {
423  if(!index.isValid())
424  return QVariant();
425 
426  switch (role)
427  {
428  case Qt::TextAlignmentRole:
429  return (int)(Qt::AlignCenter);
430  break;
431 
432  case Qt::DisplayRole:
433  {
434  if(m_currentRow != index.row())
435  {
436  m_currentRow = index.row();
437 
438  int row = (int)m_promoter->getLogicalRow(m_currentRow);
439  m_dataset->move(row);
440  }
441 
442  if(m_editor->isEdited(m_promoter->getLogicalRow(index.row()), index.column()))
443  return m_editor->getValue(m_promoter->getLogicalRow(index.row()), index.column()).c_str();
444 
445  if(m_dataset->isNull(index.column()))
446  return QVariant();
447 
448  if(m_dataset->getPropertyDataType(index.column()) == te::dt::STRING_TYPE)
449  {
450  std::string value = m_dataset->getString(index.column());
451  te::common::CharEncoding encoding = m_dataset->getPropertyCharEncoding(index.column());
452  if (encoding == te::common::UNKNOWN_CHAR_ENCODING)
453  return value.c_str();
454  else
455  return Convert2Qt(value, encoding);
456  }
457  else
458  return m_dataset->getAsString(index.column(), 6).c_str();
459  }
460  break;
461 
462  case Qt::FontRole:
463  if(m_editor->isEdited(m_promoter->getLogicalRow(index.row()), index.column()))
464  {
465  QFont f;
466  f.setBold(true);
467  f.setItalic(true);
468  return f;
469  }
470  break;
471 
472  case Qt::EditRole:
473  return data(index, Qt::DisplayRole);
474  break;
475 
476  default:
477  break;
478  }
479 
480  return QVariant();
481 }
482 
483 QVariant te::qt::widgets::DataSetTableModel::headerData(int section, Qt::Orientation orientation, int role) const
484 {
485  if(orientation == Qt::Horizontal)
486  {
487  switch(role)
488  {
489  case Qt::DisplayRole:
490  return m_dataset->getPropertyName(section).c_str();
491  break;
492 
493  case Qt::DecorationRole:
494  return (m_OIdsVisible && IsPkey(section, m_pkeysColumns)) ?
495  QIcon::fromTheme("key") :
496  QVariant();
497  break;
498 
499  case Qt::ToolTipRole:
500  return m_dataset->getPropertyName(section).c_str() + QString(" : ") + ColumnType(m_dataset->getPropertyDataType(section));
501  break;
502 
503  default:
504  return QAbstractTableModel::headerData(section, orientation, role);
505  break;
506  }
507  }
508  else
509  {
510  switch (role)
511  {
512  case Qt::DisplayRole:
513  return section+1;
514  break;
515 
516  default:
517  return QAbstractTableModel::headerData(section, orientation, role);
518  break;
519  }
520  }
521 
522  return QVariant();
523 }
524 
525 Qt::ItemFlags te::qt::widgets::DataSetTableModel::flags(const QModelIndex & index) const
526 {
527  if (index.isValid() == false)
528  return 0;
529 
530  Qt::ItemFlags flags = QAbstractItemModel::flags(index);
531 
532  flags |= Qt::ItemIsEnabled | Qt::ItemIsSelectable;
533 
534  if(m_isEditable && !IsPkey(index.column(), m_pkeysColumns))
535  flags |= Qt::ItemIsEditable;
536 
537  return flags;
538 }
539 
540 bool te::qt::widgets::DataSetTableModel::setData (const QModelIndex & index, const QVariant & value, int role)
541 {
542  if(role == Qt::EditRole)
543  {
544  try
545  {
546  switch(m_dataset->getPropertyDataType(index.column()))
547  {
548  case te::dt::INT16_TYPE:
549  case te::dt::UINT16_TYPE:
550  case te::dt::INT32_TYPE:
551  case te::dt::UINT32_TYPE:
552  case te::dt::INT64_TYPE:
553  case te::dt::UINT64_TYPE:
554  {
555  bool ok;
556  value.toInt(&ok);
557 
558  if(!ok)
559  throw te::common::Exception(tr("Invalid int value.").toStdString());
560  }
561  break;
562 
563  case te::dt::FLOAT_TYPE:
564  case te::dt::DOUBLE_TYPE:
566  {
567  bool ok;
568  value.toDouble(&ok);
569 
570  if(!ok)
571  throw te::common::Exception(tr("Invalid double value.").toStdString());
572  }
573  break;
574  }
575 
576  QString curV = data(index, Qt::DisplayRole).toString();
577  QString newV = value.toString();
578 
579  if(curV != newV)
580  m_editor->setValue(m_promoter->getLogicalRow(index.row()), index.column(), value.toString().toStdString());
581 
582  return true;
583  }
584  catch(te::common::Exception& e)
585  {
586  QMessageBox::warning(0, tr("Edition Failure"), e.what());
587  return false;
588  }
589  }
590 
591  return true;
592 }
593 
594 bool te::qt::widgets::DataSetTableModel::insertColumns(int column, int count, const QModelIndex& parent)
595 {
596  beginInsertColumns(parent, column, column+count);
597 
598  endInsertColumns();
599 
600  return true;
601 }
602 
603 bool te::qt::widgets::DataSetTableModel::removeColumns(int column, int count, const QModelIndex& parent)
604 {
605  beginRemoveColumns(parent, column, column+count);
606 
607  m_editor->columnsRemoved(column, column+count);
608 
609  endRemoveColumns();
610 
611  return true;
612 }
bool hasEditions() const
Returns true if there are unsaved editions.
std::string getValue(const int &row, const int &column)
int rowCount(const QModelIndex &parent) const
void discardEditions()
Discard editions.
A model based on te::da::DataSet.
CharEncoding
Supported charsets (character encoding).
std::map< std::pair< int, int >, std::string > m_editions
TEDATAACCESSEXPORT ObjectId * GenerateOID(DataSet *dataset, const std::vector< std::string > &names)
Definition: Utils.cpp:397
QVariant data(const QModelIndex &index, int role) const
std::auto_ptr< Editor > m_editor
Pointer to editor.
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole)
A class that models the description of a dataset.
Definition: DataSetType.h:72
virtual const char * what() const
It outputs the exception message.
Definition: Exception.cpp:58
Defines an mechanism for logical ordering of rows.
bool removeColumns(int column, int count, const QModelIndex &parent=QModelIndex())
void setPkeysColumns(const std::vector< size_t > &pkeys)
Sets the columns used as pkeys, for presentation purposes.
void setValue(std::size_t i, te::dt::AbstractData *value)
It sets the value of the i-th property.
te::da::ObjectIdSet * getObjectIdSet(const int &initRow, const int &finalRow)
Returns the ObjectIdSet begining with row initRow and ending in finalRow.
virtual ~DataSetTableModel()
Virtual destructor.
int columnCount(const QModelIndex &parent) const
void addProperty(const std::string &name, std::size_t pos, int type)
It adds a property that will be used to generate the unique ids.
Definition: ObjectIdSet.cpp:63
void showOIdsVisible(const bool &visible)
Shows an icon for indentify the columns that are used for identify objects.
void add(DataSetItem *item)
It adds a new item to the dataset and takes its ownership.
Definition: DataSet.cpp:168
virtual bool move(std::size_t i)=0
It moves the dataset internal pointer to a given position.
Implementation of a random-access dataset class for the TerraLib In-Memory Data Access driver...
Definition: DataSet.h:65
void getEditedDataSet(te::da::DataSet *in, te::mem::DataSet *out, std::vector< std::set< int > > &fields)
This class represents a set of unique ids created in the same context. i.e. from the same data set...
Definition: ObjectIdSet.h:53
virtual bool isNull(std::size_t i) const =0
It checks if the attribute value is NULL.
Qt::ItemFlags flags(const QModelIndex &index) const
std::vector< std::set< int > > getEditedLists(std::vector< int > &rows)
bool IsPkey(const int &column, const std::vector< size_t > &pkeys)
virtual std::size_t size() const =0
It returns the collection size, if it is known.
void columnRemoved(const int &column)
void promote(const te::da::ObjectIdSet *oids)
Promotes the rows identified by oids.
A class used for logical ordering of rows.
Definition: Promoter.h:69
virtual std::size_t getNumProperties() const =0
It returns the number of properties that composes an item of the dataset.
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
Definition: Exception.h:58
Promoter * m_promoter
Promoter to be used.
std::auto_ptr< te::da::DataSet > getEditions(const te::da::DataSetType *type, std::vector< std::set< int > > &ps)
Returns a memory dataset to be saved.
bool hasEditions() const
DataSetTableModel(QObject *parent=0)
Constructor.
void columnsRemoved(const int &init, const int &final)
An implementation of the DatasetItem class for the TerraLib In-Memory Data Access driver...
Definition: DataSetItem.h:56
A dataset is the unit of information manipulated by the data access module of TerraLib.
Definition: DataSet.h:112
void setEnabled(const bool &enabled)
Enable or disable the dataset presentation.
void setEditable(const bool &editable)
Sets if the model is editable or not.
QVariant headerData(int section, Qt::Orientation orientation, int role) const
void setDataSet(te::da::DataSet *dset, const bool &clearEditor=true)
Updates the data being used.
bool isEdited(const int &row, const int &column) const
Promoter * getPromoter()
Returns the pointer to the promoter being used.
TEQTWIDGETSEXPORT QColor Convert2Qt(const te::color::RGBAColor &color)
It converts a TerraLib Color to Qt Color.
Definition: Utils.cpp:216
const std::vector< std::string > & getPropertyNames() const
It returns the property names used to generated the oids.
void add(ObjectId *oid)
It adds an object id to this object id set.
Definition: ObjectIdSet.cpp:71
A template for atomic data types (integers, floats, strings and others).
Definition: SimpleData.h:59
void setValue(const int &row, const int &column, const std::string &value)
virtual int getPropertyDataType(std::size_t i) const =0
It returns the underlying data type of the property at position pos.
virtual std::auto_ptr< te::dt::AbstractData > getValue(std::size_t i) const
Method for retrieving any other type of data value stored in the data source.
Definition: DataSet.cpp:151
bool insertColumns(int column, int count, const QModelIndex &parent=QModelIndex())
QString ColumnType(const int &type)