HAL
data_table_model.cpp
Go to the documentation of this file.
1 
3 #include <algorithm>
4 #include <QToolTip>
5 #include <QRandomGenerator>
7 
8 
9 namespace hal
10 {
12  {
13  }
14 
15  int DataTableModel::columnCount(const QModelIndex &parent) const
16  {
17  Q_UNUSED(parent)
18  //return 2;
19  return 4;
20  }
21 
22  int DataTableModel::rowCount(const QModelIndex &parent) const
23  {
24  Q_UNUSED(parent)
25  return mDataEntries.size();
26  }
27 
28  QVariant DataTableModel::data(const QModelIndex &index, int role) const
29  {
30  DataEntry entry = mDataEntries[index.row()];
31  RowStyle style = mEntryToRowStyle[QPair(entry.category, entry.key)];
32 
33  if(role == Qt::DisplayRole && index.column() < columnCount())
34  {
35  switch (index.column())
36  {
37  case 0: return entry.category;
38  case 1: return entry.key;
39  case 2: return entry.dataType;
40  case 3: return style.valueString;//e.g. 0x at the front if bitvector
41  }
42  }
43  if(role == Qt::ForegroundRole && index.column() == 3 && style.valueColor.isValid())
44  return style.valueColor;
45 
46  if(role == Qt::TextAlignmentRole)
47  return Qt::AlignLeft;
48 
49 // if (role == Qt::DisplayRole){
50 // if(index.column() == 0){
51 // return (entry.key + ":");
52 // }
53 // else{
54 // return style.valueString;
55 // }
56 // }
57 
58 // if (role == Qt::ForegroundRole){
59 // if(index.column() == 1){
60 // if(style.valueColor.isValid())
61 // return style.valueColor;
62 // }
63 // }
64 
65 // else if (role == Qt::TextAlignmentRole){
66 // return Qt::AlignLeft;
67 // }
68 
69 // else if (role == Qt::ToolTipRole){
70 // if (index.column() == 0){
71 // if(!style.keyToolTip.isEmpty())
72 // return style.keyToolTip;
73 // }
74 // else {
75 // if(!style.valueToolTip.isEmpty())
76 // return style.valueToolTip;
77 // }
78 // }
79 
80  return QVariant();
81  }
82 
83  QVariant DataTableModel::headerData(int section, Qt::Orientation orientation, int role) const
84  {
85 // Q_UNUSED(section)
86 // Q_UNUSED(orientation)
87 // Q_UNUSED(role)
88 // return QVariant();
89  const char* horizontalHeader[] = { "Category", "Key", "Type", "Value"};
90  if (orientation == Qt::Horizontal && role == Qt::DisplayRole && section < columnCount())
91  return QString(horizontalHeader[section]);
92 
93  return QVariant();
94  }
95 
96  bool DataTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
97  {
98  Q_UNUSED(index)
99  Q_UNUSED(value)
100  Q_UNUSED(role)
101  return false;
102  }
103 
105  {
106  return mDataEntries.at(row);
107  }
108 
109  void DataTableModel::updateData(const std::map<std::tuple<std::string, std::string>, std::tuple<std::string, std::string>>& dataMap)
110  {
112  mDataEntries.clear();
113  mEntryToRowStyle.clear();
114  for(const auto& [key, value] : dataMap)
115  {
116  DataEntry e;
117  e.category = QString::fromStdString(std::get<0>(key));
118  e.key = QString::fromStdString(std::get<1>(key));
119  e.dataType = QString::fromStdString(std::get<0>(value));
120  e.value = QString::fromStdString(std::get<1>(value));
121 
122  mDataEntries.append(e);
123  }
124  // The data is sorted by category first and then by key. However the category generic is always displayed first.
125  qSort(mDataEntries.begin(), mDataEntries.end(),
126  [](const DataEntry a, const DataEntry b) -> bool
127  {
128 
129  if(a.category == b.category)
130  {
131  return (a.key < b.key);
132  }
133  else
134  {
135  if(a.category == "generic")
136  return true;
137  else if(b.category == "generic")
138  return false;
139  else
140  return (a.category < b.category);
141  }
142  });
143 
144  // Compute the appearance
145  int rowIdx = 0;
146  for(const DataEntry& entry : mDataEntries)
147  {
148  mEntryToRowStyle[QPair(entry.category, entry.key)] = getRowStyleByEntry(entry, rowIdx);
149  rowIdx++;
150  }
151 
152  Q_EMIT layoutChanged();
153  }
154 
155  DataTableModel::RowStyle DataTableModel::getRowStyleByEntry(const DataEntry& entry, int rowIdx) const
156  {
157  RowStyle style;
158  style.keyFont = QFont();
159  style.keyToolTip = QString();
160  style.valueToolTip = QString();
161  style.valueColor = QColor();
162 
163  // Sets the value string and color considering its data type
164  if(entry.dataType == "string")
165  {
166  style.valueString = QString("\"%1\"").arg(entry.value);
167  style.valueColor = PythonQssAdapter::instance()->doubleQuotedStringColor();
168  }
169  else if(entry.dataType == "bit_value" || entry.dataType == "bit_vector")
170  {
171  style.valueString = QString("0x%1").arg(entry.value);
172  style.valueColor = PythonQssAdapter::instance()->numberColor();
173  }
174  else if(entry.dataType == "integer")
175  {
176  style.valueString = entry.value;
177  style.valueColor = PythonQssAdapter::instance()->numberColor();
178  }
179  else
180  {
181  style.valueString = entry.value;
182  }
183 
184 
185  // Hacky solution to prevent that the tooltip in neighboring rows does not change position if the tooltip entry is the same.
186  // Therefore, two different space types are used so that Qt thinks these are different entries.
187  if(rowIdx%2 == 0)
188  {
189  style.keyToolTip = entry.category + " ";
190  style.valueToolTip = entry.dataType + " ";
191  }
192  else
193  {
194  //U+00A0 is a no-break space and therefore another type of space
195  style.keyToolTip = entry.category + QChar(0x00A0);
196  style.valueToolTip = entry.dataType + QChar(0x00A0);
197  }
198 
199  return style;
200  }
201 
202 } // namespace hal
203 
204 
DataTableModel(QObject *parent=nullptr)
bool setData(const QModelIndex &index, const QVariant &value, int role) override
int columnCount(const QModelIndex &parent=QModelIndex()) const override
DataEntry getEntryAtRow(int row) const
QVariant data(const QModelIndex &index, int role) const override
void updateData(const std::map< std::tuple< std::string, std::string >, std::tuple< std::string, std::string >> &dc)
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
void layoutAboutToBeChanged(const QList< QPersistentModelIndex > &parents, QAbstractItemModel::LayoutChangeHint hint)
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
void clear()
int column() const const
int row() const const
Q_EMITQ_EMIT
QObject * parent() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString fromStdString(const std::string &str)
AlignLeft
DisplayRole
Orientation
QString key
The data's category.
QString dataType
The data's key.
QString value
QString category