Fraxinus  16.5.0-fx-rc1
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxTreeItemModel.cpp
Go to the documentation of this file.
1 #include "cxTreeItemModel.h"
2 
3 //#include "cxBrowserWidget.h"
4 
5 #include <QTreeWidget>
6 #include <QTreeWidgetItem>
7 #include <QStringList>
8 #include <QVBoxLayout>
10 #include "cxViewService.h"
11 #include "cxRep.h"
12 #include "cxViewGroupData.h"
13 #include "cxTypeConversions.h"
14 #include "cxTreeRepository.h"
15 #include "cxLogger.h"
16 #include <QVariant>
17 #include "cxStringListProperty.h"
18 
19 namespace cx
20 {
21 
22 
23 
24 TreeItemModel::TreeItemModel(XmlOptionFile options, VisServicesPtr services, QObject* parent) :
25  QAbstractItemModel(parent),
26  mServices(services),
27  mOptions(options)
28 {
29  mSelectionModel = NULL;
30  mNameIndex = 1;
31  mColorIndex = 0;
32  mViewGroupIndex = 2;
33  mViewGroupCount = 3;
34 
35  this->createShowColumnsProperty();
36  this->onShowColumnsChanged();
37 
38  mRepository = TreeRepository::create(options.descend("repository"), services);
39  connect(mRepository.get(), &TreeRepository::invalidated, this, &TreeItemModel::beginResetModel);
40  connect(mRepository.get(), &TreeRepository::loaded, this, &TreeItemModel::loaded);
41  connect(mRepository.get(), &TreeRepository::changed, this, &TreeItemModel::onRepositoryChanged);
42 }
43 
44 void TreeItemModel::onRepositoryChanged()
45 {
46  emit dataChanged(QModelIndex(),QModelIndex());
47 }
48 
49 
51 {
52 // CX_LOG_CHANNEL_DEBUG("CA") << "TreeItemModel::buildTree() B";
53  this->beginResetModel();
54  mRepository->update();
55  this->endResetModel();
56 // CX_LOG_CHANNEL_DEBUG("CA") << "TreeItemModel::buildTree() E";
57 }
58 
59 void TreeItemModel::createShowColumnsProperty()
60 {
61  QStringList range = QStringList() << "color" << "vg0" << "vg1" << "vg2" << "vg3";
62  QStringList defvals = range;
63  defvals.pop_back();
64  defvals.pop_back();
65 
66  std::map<QString, QString> names;
67  names["color"] = "Color";
68  for (unsigned i=0; i<4; ++i)
69  names[QString("vg%1").arg(i)] = QString("View Group %1").arg(i);
70 
71 // QStringList range = QStringList() << "Color"
72 // << "View Group 0"
73 // << "View Group 1"
74 // << "View Group 2"
75 // << "View Group 3";
76  mShowColumnsProperty = StringListProperty::initialize("visible_columns",
77  "Columns",
78  "Select visible columns",
79  range,
80  range,
81  mOptions.getElement());
82  mShowColumnsProperty->setDisplayNames(names);
83  connect(mShowColumnsProperty.get(), &Property::changed, this, &TreeItemModel::onShowColumnsChanged);
84 }
85 
86 void TreeItemModel::onShowColumnsChanged()
87 {
88 // CX_LOG_CHANNEL_DEBUG("CA") << "TreeItemModel::onShowColumnsChanged()";
89  this->beginResetModel();
90 
91  int none = 1000;
92  QStringList cols = mShowColumnsProperty->getValue();
93 
94  mColumnCount = 0;
95  mNameIndex = mColumnCount++;
96  mColorIndex = cols.contains("color") ? mColumnCount++ : none;
97  mViewGroupCount = 0;
98  while (cols.contains(QString("vg%1").arg(mViewGroupCount)))
99  ++mViewGroupCount;
100  mViewGroupIndex = (mViewGroupCount>0) ? mColumnCount : none;
101  mColumnCount += mViewGroupCount;
102 
103 // CX_LOG_CHANNEL_DEBUG("CA") << "mColorIndex: " << mColorIndex;
104 // CX_LOG_CHANNEL_DEBUG("CA") << "mNameIndex: " << mNameIndex;
105 // CX_LOG_CHANNEL_DEBUG("CA") << "mViewGroupIndex: " << mViewGroupIndex;
106 // CX_LOG_CHANNEL_DEBUG("CA") << "mViewGroupCount: " << mViewGroupCount;
107 // CX_LOG_CHANNEL_DEBUG("CA") << "mColumnCount: " << mColumnCount;
108 
109 // this->endResetModel();
110 // emit hasBeenReset();
111 }
112 
113 
114 
115 void TreeItemModel::setSelectionModel(QItemSelectionModel* selectionModel)
116 {
117  mSelectionModel = selectionModel;
118  connect(mSelectionModel, &QItemSelectionModel::currentChanged,
119  this, &TreeItemModel::currentItemChangedSlot);
120 }
121 
123 {
124 }
125 
126 void TreeItemModel::currentItemChangedSlot(const QModelIndex& current, const QModelIndex& previous)
127 {
128  TreeNode *item = this->itemFromIndex(current);
129  if (!item)
130  return;
131  item->activate();
132  emit currentItemChanged();
133 }
134 
136 {
137  QModelIndex mi = mSelectionModel->currentIndex();
138  return this->getNodeFromIndex(mi);
139 }
140 
142 {
143  TreeNode *item = this->itemFromIndex(index);
144  if (!item)
145  return TreeNodePtr();
146  return mRepository->getNode(item->getUid());
147 }
148 
149 TreeNode* TreeItemModel::itemFromIndex(const QModelIndex& index) const
150 {
151  if (!index.isValid())
152  return mRepository->getTopNode().get();
153  else
154  return static_cast<TreeNode*>(index.internalPointer());
155 }
156 
157 int TreeItemModel::columnCount(const QModelIndex& parent) const
158 {
159 // if (parent.isValid() && (parent.column() != mNameIndex)) // ignore for all but first column
160 // return 0;
161  return mColumnCount;
162 }
163 
164 int TreeItemModel::rowCount(const QModelIndex& parent) const
165 {
166 // if (parent.isValid() && (parent.column() != mNameIndex)) // ignore for all but first column
167 // return 0;
168  TreeNode *parentItem = this->itemFromIndex(parent);
169  return parentItem->getVisibleChildren().size();
170 }
171 
172 QVariant TreeItemModel::data(const QModelIndex& index, int role) const
173 {
174  if (role==Qt::DisplayRole)
175  {
176  if (index.column()==mNameIndex)
177  {
178  TreeNode *item = this->itemFromIndex(index);
179  return item->getName();
180  }
181  }
182  if (role==Qt::CheckStateRole)
183  {
184  if (this->isViewGroupColumn(index.column()))
185  {
186  TreeNode *item = this->itemFromIndex(index);
187  return item->getViewGroupVisibility(this->viewGroupFromColumn(index.column()));
188  }
189  }
190  if (role==Qt::ToolTipRole || role==Qt::StatusTipRole)
191  {
192  TreeNode *item = this->itemFromIndex(index);
193  if (index.column()==mNameIndex)
194  return QString("%1 of type %2").arg(item->getName()).arg(item->getType());
195  if (this->isViewGroupColumn(index.column()))
196  return QString("Set visibility of %1 in view group %2")
197  .arg(item->getName()).arg(this->viewGroupFromColumn(index.column()));
198  }
199  if (role==Qt::DecorationRole)
200  {
201  TreeNode *item = this->itemFromIndex(index);
202  if (index.column()==mNameIndex)
203  return item->getIcon();
204  if (index.column()==mColorIndex)
205  {
206  if (item->getColor().canConvert<QColor>())
207  return this->getColorIcon(item->getColor().value<QColor>());
208  }
209  }
210  if (role==Qt::FontRole)
211  {
212  if (index.column()==mNameIndex)
213  {
214  TreeNode *item = this->itemFromIndex(index);
215  return item->getFont();
216  }
217  }
218  if (role==Qt::ForegroundRole)
219  {
220  if (index.column()==mNameIndex)
221  {
222  TreeNode *item = this->itemFromIndex(index);
223 // if (item->useColoredName())
224  {
225  QVariant color = item->getColor();
226  if (color.canConvert<QColor>())
227  {
228  QColor oldColor = color.value<QColor>().toHsv();
229  QColor newColor = this->adjustColorToContrastWithWhite(oldColor);
230 // CX_LOG_CHANNEL_DEBUG("CA") << "color " << item->getName() << "";
231 // qDebug() << "color " << item->getName() << " " << oldColor << " new=" << newColor;
232  return newColor;
233  }
234  }
235  }
236  }
237  return QVariant();
238 }
239 
240 
241 bool TreeItemModel::setData(const QModelIndex& index, const QVariant& value, int role)
242 {
243  if (role==Qt::CheckStateRole)
244  {
245  if (this->isViewGroupColumn(index.column()))
246  {
247  TreeNode *item = this->itemFromIndex(index);
248  item->setViewGroupVisibility(this->viewGroupFromColumn(index.column()), value.value<int>());
249  }
250  return true;
251  }
252  return false;
253 }
254 
255 Qt::ItemFlags TreeItemModel::flags(const QModelIndex& index) const
256 {
257  if (index.column()>0)
258  return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
259  else
260  return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
261 }
262 
263 bool TreeItemModel::isViewGroupColumn(int col) const
264 {
265  return ( (0<=(col-mViewGroupIndex))
266  &&
267  ((col-mViewGroupIndex) < mViewGroupCount)
268  );
269 }
270 int TreeItemModel::viewGroupFromColumn(int col) const
271 {
272  return (col-mViewGroupIndex);
273 }
274 
275 QVariant TreeItemModel::headerData(int section, Qt::Orientation orientation, int role) const
276 {
277  if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
278  {
279  if (section==mNameIndex)
280  return "Item";
281  if (section==mColorIndex)
282  return ""; // keep short + out of the way of the toolbar button
283  if (this->isViewGroupColumn(section))
284  return QString("V%1").arg(this->viewGroupFromColumn(section));
285  }
286  return QVariant();
287 }
288 
289 QModelIndex TreeItemModel::index(int row, int column, const QModelIndex& parent) const
290 {
291  TreeNode *parentItem = this->itemFromIndex(parent);
292  std::vector<TreeNodePtr> children = parentItem->getVisibleChildren();
293  if (row < children.size())
294  {
295  return createIndex(row, column, children[row].get());
296  }
297  else
298  {
299  return QModelIndex();
300  }
301 }
302 
303 QModelIndex TreeItemModel::parent(const QModelIndex& index) const
304 {
305  TreeNode *childItem = this->itemFromIndex(index);
306 
307  if (!childItem)
308  return QModelIndex();
309 
310  TreeNode *parentItem = childItem->getVisibleParent().get();
311 
312  if (parentItem == mRepository->getTopNode().get())
313  return QModelIndex();
314 
315  // find row of parent within grandparent
316  TreeNodePtr grandParent = parentItem->getVisibleParent();
317  int row = 0;
318  if (grandParent)
319  {
320  std::vector<TreeNodePtr> parentSiblings = grandParent->getVisibleChildren();
321  for (row=0; row<parentSiblings.size(); ++row)
322  if (parentItem==parentSiblings[row].get())
323  break;
324  }
325 
326  return createIndex(row, mNameIndex, parentItem);
327 }
328 
329 QIcon TreeItemModel::getColorIcon(QColor color) const
330 {
331  QImage image(QSize(128,128), QImage::Format_RGBA8888);
332  QPainter painter(&image);
333  painter.fillRect(image.rect(), QColor("white"));
334  painter.setBrush(QBrush(color));
335  painter.drawRoundedRect(image.rect(), 75, 75, Qt::RelativeSize);
336 // painter.drawEllipse(image.rect());
337  return QIcon(QPixmap::fromImage(image));
338 }
339 
340 QColor TreeItemModel::adjustColorToContrastWithWhite(QColor color) const
341 {
342  // use some tricks in HSV space to get contrasting colors while
343  // keeping the original color as much as possible.
344  //
345  // for colors: strengthen the saturation: s' = s+(1-s)/2
346  // for for grayscale: lower value, or give up for whites:
347  // if s<0.1: v = max(0.7, v)
348  double h = color.hueF();
349  double s = color.hsvSaturationF();
350  double v = color.valueF();
351 
352  double isChromatic = s > 0.1; // our definition
353  if (isChromatic)
354  {
355  s = s+(1.0-s)/2;
356  }
357  else
358  {
359  v = std::min(0.6, v);
360  }
361 
362  return QColor::fromHsvF(h,s,v);
363 }
364 
365 
366 
367 }//end namespace cx
368 
void currentItemChanged()
boost::shared_ptr< TreeNode > TreeNodePtr
virtual std::vector< TreeNodePtr > getVisibleChildren() const =0
virtual QString getUid() const =0
boost::shared_ptr< class VisServices > VisServicesPtr
Definition: cxMainWindow.h:62
virtual Qt::ItemFlags flags(const QModelIndex &index) const
TreeNodePtr getCurrentItem()
virtual bool setData(const QModelIndex &index, const QVariant &value, int role)
virtual QVariant getColor() const =0
virtual QModelIndex parent(const QModelIndex &index) const
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const
virtual QIcon getIcon() const =0
QDomElement getElement()
return the current element
static StringListPropertyPtr initialize(const QString &uid, QString name, QString help, QStringList value, QStringList range, QDomNode root=QDomNode())
virtual QString getType() const =0
TreeItemModel(XmlOptionFile options, VisServicesPtr services, QObject *parent=0)
virtual QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const
virtual void setViewGroupVisibility(int index, bool value)=0
virtual QVariant getViewGroupVisibility(int index) const =0
virtual void activate()=0
static TreeRepositoryPtr create(XmlOptionFile options, VisServicesPtr services)
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
void changed()
emit when the underlying data value is changed: The user interface will be updated.
virtual QString getName() const =0
virtual QVariant getFont() const =0
void setSelectionModel(QItemSelectionModel *selectionModel)
TreeNodePtr getNodeFromIndex(const QModelIndex &index)
virtual TreeNodePtr getVisibleParent() const =0
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const
virtual QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
Helper class for xml files used to store ssc/cx data.
XmlOptionFile descend(QString element) const
step one level down in the xml tree