curvetree_view.cpp
Go to the documentation of this file.
1 /*
2  * This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
5  */
6 
7 #include "curvetree_view.h"
8 #include "curvelist_panel.h"
9 #include <QTimer>
10 #include <QFontDatabase>
11 #include <QObject>
12 #include <QDebug>
13 #include <QToolTip>
14 #include <QKeySequence>
15 #include <QClipboard>
16 
17 class TreeWidgetItem : public QTreeWidgetItem
18 {
19 public:
20  TreeWidgetItem(QTreeWidgetItem* parent) : QTreeWidgetItem(parent)
21  {
22  }
23 
24  bool operator<(const QTreeWidgetItem& other) const
25  {
26  return doj::alphanum_impl(this->text(0).toLocal8Bit(), other.text(0).toLocal8Bit()) <
27  0;
28  }
29 };
30 
32  : QTreeWidget(parent), CurvesView(parent)
33 {
34  setColumnCount(2);
35  setEditTriggers(NoEditTriggers);
36  setDragEnabled(false);
37  setDefaultDropAction(Qt::IgnoreAction);
38  setDragDropOverwriteMode(false);
39  setMouseTracking(true);
40  setDragDropMode(NoDragDrop);
41  viewport()->installEventFilter(this);
42  setSelectionMode(ExtendedSelection);
43  setSelectionBehavior(QAbstractItemView::SelectRows);
44  setFocusPolicy(Qt::ClickFocus);
45 
46  header()->setVisible(false);
47  header()->setStretchLastSection(true);
48  header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
49  setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
50 
51  connect(this, &QTreeWidget::itemDoubleClicked, this,
52  [this](QTreeWidgetItem* item, int column) {
53  if (column == 0)
54  {
55  expandChildren(!item->isExpanded(), item);
56  }
57  });
58 
59  connect(selectionModel(), &QItemSelectionModel::selectionChanged, this, [this]() {
60  if (getSelectedNames().empty())
61  {
62  // this looks nicer
63  clearFocus();
64  setFocusPolicy(Qt::NoFocus);
65  }
66  else
67  {
68  // this focus policy is needed to allow CurveListPanel::keyPressEvent to be called
69  setFocusPolicy(Qt::ClickFocus);
70  }
71  });
72  _tooltip_timer = new QTimer(this);
73  connect(_tooltip_timer, &QTimer::timeout, this, [this]() {
74  if (_tooltip_item)
75  {
76  auto tooltip = _tooltip_item->data(0, CustomRoles::ToolTip);
77  if (tooltip.isValid())
78  {
79  QToolTip::showText(_tooltip_pos, tooltip.toString(), this, QRect(), 10000);
80  }
81  }
82  });
83  _tooltip_timer->start(100);
84 }
85 
87 {
88  _tooltip_item = nullptr;
89  _tooltip_timer->stop();
91  _leaf_count = 0;
92  _hidden_count = 0;
93 }
94 
95 void CurveTreeView::addItem(const QString& group_name, const QString& tree_name,
96  const QString& plot_ID)
97 {
98  QSettings settings; /*
99  * This Source Code Form is subject to the terms of the Mozilla
100  * Public License, v. 2.0. If a copy of the MPL was not distributed
101  * with this file, You can obtain one at
102  * https://mozilla.org/MPL/2.0/.
103  */
104 
105  bool use_separator = settings.value("Preferences::use_separator", true).toBool();
106 
107  QStringList parts;
108  if (use_separator)
109  {
110  parts = tree_name.split('/', PJ::SkipEmptyParts);
111  }
112  else
113  {
114  parts.push_back(tree_name);
115  }
116 
117  if (parts.size() == 0)
118  {
119  return;
120  }
121 
122  bool prefix_is_group = tree_name.startsWith(group_name);
123  bool hasGroup = !group_name.isEmpty();
124  auto group_parts = group_name.split('/', PJ::SkipEmptyParts);
125 
126  if (hasGroup && !prefix_is_group)
127  {
128  parts = group_parts + parts;
129  }
130 
131  QTreeWidgetItem* tree_parent = this->invisibleRootItem();
132 
133  for (int i = 0; i < parts.size(); i++)
134  {
135  bool is_leaf = (i == parts.size() - 1);
136  const auto& part = parts[i];
137 
138  QTreeWidgetItem* matching_child = nullptr;
139 
140  for (int c = 0; c < tree_parent->childCount(); c++)
141  {
142  QTreeWidgetItem* tree_child = tree_parent->child(c);
143  if (tree_child->text(0) == part)
144  {
145  matching_child = tree_child;
146  break;
147  }
148  }
149 
150  if (matching_child)
151  {
152  tree_parent = matching_child;
153  }
154  else
155  {
156  QTreeWidgetItem* child_item = new TreeWidgetItem(tree_parent);
157  child_item->setText(0, part);
158  child_item->setText(1, is_leaf ? "-" : "");
159 
160  bool isGroupCell = (i < group_parts.size());
161 
162  QFont font = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
163  font.setPointSize(_point_size);
164  // font.setBold(isGroupCell);
165  child_item->setFont(0, font);
166 
167  font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
168  font.setPointSize(_point_size - 2);
169  child_item->setFont(1, font);
170  child_item->setTextAlignment(1, Qt::AlignRight);
171 
172  tree_parent = child_item;
173 
174  auto current_flag = child_item->flags();
175 
176  if (isGroupCell)
177  {
178  child_item->setData(0, Name, group_name);
179  child_item->setData(0, IsGroupName, (i + 1) == group_parts.size());
180  }
181 
182  if (is_leaf)
183  {
184  child_item->setFlags(current_flag | Qt::ItemIsSelectable);
185  child_item->setData(0, Name, plot_ID);
186  }
187  else
188  {
189  child_item->setFlags(current_flag & (~Qt::ItemIsSelectable));
190  }
191  }
192  }
193  _leaf_count++;
194 }
195 
197 {
198  invisibleRootItem()->sortChildren(0, Qt::AscendingOrder);
199  treeVisitor([&](QTreeWidgetItem* item) { item->sortChildren(0, Qt::AscendingOrder); });
200  header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
201 }
202 
203 std::vector<std::string> CurveTreeView::getSelectedNames()
204 {
205  std::vector<std::string> non_hidden_list;
206 
207  for (const auto& item : selectedItems())
208  {
209  non_hidden_list.push_back(item->data(0, Qt::UserRole).toString().toStdString());
210  }
211  return non_hidden_list;
212 }
213 
215 {
216  header()->setSectionResizeMode(0, QHeaderView::Fixed);
217  header()->setSectionResizeMode(1, QHeaderView::Fixed);
218 
219  treeVisitor([this](QTreeWidgetItem* item) {
220  auto font = item->font(0);
221  font.setPointSize(_point_size);
222  item->setFont(0, font);
223  font = item->font(1);
224  font.setPointSize(_point_size - 2);
225  item->setFont(1, font);
226  });
227 
228  header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
229  header()->setSectionResizeMode(1, QHeaderView::Stretch);
230 }
231 
232 bool CurveTreeView::applyVisibilityFilter(const QString& search_string)
233 {
234  bool updated = false;
235  _hidden_count = 0;
236 
237  QStringList spaced_items = search_string.split(' ', PJ::SkipEmptyParts);
238 
239  auto hideFunc = [&](QTreeWidgetItem* item) {
240  QString name = item->data(0, Qt::UserRole).toString();
241  if (name.isEmpty())
242  {
243  return; // not a leaf
244  }
245  bool toHide = false;
246 
247  if (search_string.isEmpty() == false)
248  {
249  for (const auto& spaced_item : spaced_items)
250  {
251  if (name.contains(spaced_item, Qt::CaseInsensitive) == false)
252  {
253  toHide = true;
254  break;
255  }
256  }
257  }
258  if (toHide)
259  {
260  _hidden_count++;
261  }
262 
263  if (toHide != item->isHidden())
264  {
265  updated = true;
266  }
267 
268  item->setHidden(toHide);
269 
270  // hide the parent if necessary
271  auto parent = item->parent();
272  while (parent)
273  {
274  bool all_children_hidden = true;
275  for (int c = 0; c < parent->childCount(); c++)
276  {
277  if (!parent->child(c)->isHidden())
278  {
279  all_children_hidden = false;
280  break;
281  }
282  }
283  auto parent_hidden = parent->isHidden();
284  if (all_children_hidden != parent_hidden)
285  {
286  parent->setHidden(all_children_hidden);
287  parent = parent->parent();
288  }
289  else
290  {
291  break;
292  }
293  }
294  };
295 
296  treeVisitor(hideFunc);
297  //-------------
298 
299  return updated;
300 }
301 
302 bool CurveTreeView::eventFilter(QObject* object, QEvent* event)
303 {
304  if (event->type() == QEvent::MouseMove)
305  {
306  auto mouse_event = static_cast<QMouseEvent*>(event);
307  auto* item = itemAt(mouse_event->pos());
308  if (item)
309  {
310  _tooltip_pos = mapToGlobal(mouse_event->pos());
311  }
312  _tooltip_item = item;
313  }
314 
315  if (event->type() == QEvent::Leave)
316  {
317  _tooltip_item = nullptr;
318  }
319 
320  bool ret = CurvesView::eventFilterBase(object, event);
321  if (!ret)
322  {
323  return QWidget::eventFilter(object, event);
324  }
325  else
326  {
327  return true;
328  }
329 }
330 
331 void CurveTreeView::removeCurve(const QString& to_be_deleted)
332 {
333  auto removeFunc = [&](QTreeWidgetItem* item) {
334  QString curve_name = item->data(0, Qt::UserRole).toString();
335  if (curve_name == to_be_deleted)
336  {
337  _leaf_count--;
338  auto parent_item = item->parent();
339  if (!parent_item)
340  {
341  parent_item = invisibleRootItem();
342  }
343  parent_item->removeChild(item);
344 
345  while (parent_item->childCount() == 0 && parent_item != invisibleRootItem())
346  {
347  auto prev_item = parent_item;
348  parent_item = parent_item->parent();
349  if (!parent_item)
350  {
351  parent_item = invisibleRootItem();
352  }
353  parent_item->removeChild(prev_item);
354  }
355  }
356  };
357 
358  // just in case
359  _tooltip_item = nullptr;
360  treeVisitor(removeFunc);
361 }
362 
364 {
365  setViewResizeEnabled(true);
366  setColumnHidden(1, hide);
367 }
368 
369 void CurveTreeView::treeVisitor(std::function<void(QTreeWidgetItem*)> visitor)
370 {
371  std::function<void(QTreeWidgetItem*)> recursiveFunction;
372  recursiveFunction = [&](QTreeWidgetItem* item) {
373  visitor(item);
374  for (int c = 0; c < item->childCount(); c++)
375  {
376  recursiveFunction(item->child(c));
377  }
378  };
379 
380  for (int c = 0; c < invisibleRootItem()->childCount(); c++)
381  {
382  recursiveFunction(invisibleRootItem()->child(c));
383  }
384 }
385 
386 void CurveTreeView::keyPressEvent(QKeyEvent* event)
387 {
388  if (event->matches(QKeySequence::Copy))
389  {
390  auto selected = selectedItems();
391  if (selected.size() > 0)
392  {
393  QClipboard* clipboard = QApplication::clipboard();
394  clipboard->setText(selected.front()->data(0, Name).toString());
395  }
396  }
397 }
398 
399 void CurveTreeView::expandChildren(bool expanded, QTreeWidgetItem* item)
400 {
401  int childCount = item->childCount();
402  for (int i = 0; i < childCount; i++)
403  {
404  const auto child = item->child(i);
405  // Recursively call the function for each child node.
406  if (child->childCount() > 0)
407  {
408  child->setExpanded(expanded);
409  expandChildren(expanded, child);
410  }
411  }
412 }
CurveTreeView::eventFilter
bool eventFilter(QObject *object, QEvent *event) override
Definition: curvetree_view.cpp:302
CurveTreeView::_tooltip_timer
QTimer * _tooltip_timer
Definition: curvetree_view.h:57
IsGroupName
@ IsGroupName
Definition: curvelist_view.h:47
CurvesView::eventFilterBase
bool eventFilterBase(QObject *object, QEvent *event)
Definition: curvelist_view.cpp:209
curvetree_view.h
CurveTreeView::keyPressEvent
virtual void keyPressEvent(QKeyEvent *) override
Definition: curvetree_view.cpp:386
CurveTreeView::addItem
void addItem(const QString &prefix, const QString &tree_name, const QString &plot_ID) override
Definition: curvetree_view.cpp:95
PJ::SkipEmptyParts
const auto SkipEmptyParts
Definition: plotdatabase.h:31
TreeWidgetItem::operator<
bool operator<(const QTreeWidgetItem &other) const
Definition: curvetree_view.cpp:24
CurvesView
Definition: curvelist_view.h:51
CurveTreeView::expandChildren
void expandChildren(bool expanded, QTreeWidgetItem *item)
Definition: curvetree_view.cpp:399
CurveListPanel
Definition: curvelist_panel.h:29
CurveTreeView::_tooltip_pos
QPoint _tooltip_pos
Definition: curvetree_view.h:59
CurveTreeView::_tooltip_item
QTreeWidgetItem * _tooltip_item
Definition: curvetree_view.h:58
curvelist_panel.h
sol::stack::clear
void clear(lua_State *L, int table_index)
Definition: sol.hpp:11710
ToolTip
@ ToolTip
Definition: curvelist_view.h:48
CurveTreeView::refreshColumns
void refreshColumns() override
Definition: curvetree_view.cpp:196
CurveTreeView::setViewResizeEnabled
void setViewResizeEnabled(bool) override
Definition: curvetree_view.h:41
Name
@ Name
Definition: curvelist_view.h:46
CurveTreeView::applyVisibilityFilter
bool applyVisibilityFilter(const QString &filter_string) override
Definition: curvetree_view.cpp:232
nlohmann::detail::void
j template void())
Definition: json.hpp:4061
CurveTreeView::treeVisitor
void treeVisitor(std::function< void(QTreeWidgetItem *)> visitor)
Definition: curvetree_view.cpp:369
CurveTreeView::refreshFontSize
void refreshFontSize() override
Definition: curvetree_view.cpp:214
CurveTreeView::_leaf_count
int _leaf_count
Definition: curvetree_view.h:55
TreeWidgetItem
Definition: curvetree_view.cpp:17
CurvesView::_point_size
int _point_size
Definition: curvelist_view.h:86
CurveTreeView::hideValuesColumn
virtual void hideValuesColumn(bool hide) override
Definition: curvetree_view.cpp:363
CurveTreeView::getSelectedNames
std::vector< std::string > getSelectedNames() override
Definition: curvetree_view.cpp:203
CurveTreeView::_hidden_count
int _hidden_count
Definition: curvetree_view.h:54
CurveTreeView::removeCurve
void removeCurve(const QString &name) override
Definition: curvetree_view.cpp:331
CurveTreeView::CurveTreeView
CurveTreeView(CurveListPanel *parent)
Definition: curvetree_view.cpp:31
CurveTreeView::clear
void clear() override
Definition: curvetree_view.cpp:86
header
const std::string header
TreeWidgetItem::TreeWidgetItem
TreeWidgetItem(QTreeWidgetItem *parent)
Definition: curvetree_view.cpp:20
mqtt_test.ret
ret
Definition: mqtt_test.py:30


plotjuggler
Author(s): Davide Faconti
autogenerated on Mon Nov 11 2024 03:23:43