maxLibQt
TreeComboBox.cpp
Go to the documentation of this file.
1 /*
2  TreeComboBox
3 
4  COPYRIGHT: (c)2017 Maxim Paperno; All Right Reserved.
5  Contact: http://www.WorldDesign.com/contact
6 
7  LICENSE:
8 
9  Commercial License Usage
10  Licensees holding valid commercial licenses may use this file in
11  accordance with the terms contained in a written agreement between
12  you and the copyright holder.
13 
14  GNU General Public License Usage
15  Alternatively, this file may be used under the terms of the GNU
16  General Public License as published by the Free Software Foundation,
17  either version 3 of the License, or (at your option) any later version.
18 
19  This program is distributed in the hope that it will be useful,
20  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  GNU General Public License for more details.
23 
24  A copy of the GNU General Public License is available at <http://www.gnu.org/licenses/>.
25 */
26 
27 #include "TreeComboBox.h"
28 
29 #include <QAccessible>
30 #include <QGuiApplication>
31 #include <QDebug>
32 #include <QDesktopWidget>
33 #include <QHeaderView>
34 #include <QMouseEvent>
35 #include <QPainter>
36 #include <QScreen>
37 #include <QStack>
38 #include <QStandardItemModel>
39 
40 /*
41  TreeComboItemDelegate
42 */
43 
44 // static
46  return index.data(Qt::AccessibleDescriptionRole).toString() == QLatin1String("separator");
47 }
48 
49 // static
51  return index.data(Qt::AccessibleDescriptionRole).toString() == QLatin1String("parent");
52 }
53 
54 // static
56  model->setData(index, QString::fromLatin1("separator"), Qt::AccessibleDescriptionRole);
57  if (QStandardItemModel *m = qobject_cast<QStandardItemModel*>(model))
58  if (QStandardItem *item = m->itemFromIndex(index))
59  item->setFlags(item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEnabled));
60 }
61 
62 // static
63 void TreeComboItemDelegate::setParent(QAbstractItemModel *model, const QModelIndex &index, const bool selectable) {
65  if (!selectable) {
66  if (QStandardItemModel *m = qobject_cast<QStandardItemModel*>(model))
67  if (QStandardItem * item = m->itemFromIndex(index))
68  item->setFlags(item->flags() & ~(Qt::ItemIsSelectable));
69  }
70 }
71 
72 void TreeComboItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
73 {
74  if (isSeparator(index)) {
75  QPen pen = painter->pen();
76  pen.setColor(option.palette.color(QPalette::Active, QPalette::Dark));
77  pen.setWidthF(1.5);
78  painter->save();
79  painter->setPen(pen);
81  painter->drawLine(option.rect.left(), option.rect.center().y(), option.rect.right(), option.rect.center().y());
82  painter->restore();
83  return;
84  }
85  else if (isParent(index)) {
86  QStyleOptionViewItem opt = option;
87  opt.state |= QStyle::State_Enabled; // make sure it looks enabled even if it isn't
88  opt.font.setBold(true);
89  opt.font.setItalic(true);
90  QStyledItemDelegate::paint(painter, opt, index);
91  return;
92  }
93 
94  QStyledItemDelegate::paint(painter, option, index);
95 }
96 
98 {
99  if(index.data(Qt::AccessibleDescriptionRole).toString() == QLatin1String("separator"))
100  return QSize(0, 5);
101  return QStyledItemDelegate::sizeHint(option, index);
102 }
103 
104 
105 /*
106  TreeComboBox
107 */
108 
110  QComboBox(parent),
111  m_view(NULL),
112  m_nextDataId(0),
113  m_autoData(true),
114  m_skipNextHide(false)
115 {
116  setView();
119  setMaxVisibleItems(30);
120 }
121 
123 {
124  if (view()) {
125  view()->removeEventFilter(this);
126  view()->viewport()->removeEventFilter(this);
127  disconnect(view(), 0, this, 0);
128  }
129 
130  QTreeView * treeView = NULL;
131  if (!itemView || !(treeView = qobject_cast<QTreeView *>(itemView))) {
132  if (!m_view)
133  m_view = new TreeComboBoxView;
134  if (itemView && !treeView)
135  qWarning() << "TreeComboBox: Only QTreeView and derived classes are allowed, using default view instead.";
136  }
137  else {
138  m_view = treeView;
139  }
140 
141  m_view->setItemsExpandable(true);
143  m_view->setHeaderHidden(true);
144  m_view->setWordWrap(false);
148 
150  view()->installEventFilter(this);
151  view()->viewport()->installEventFilter(this);
155 }
156 
158 {
159  if (this->model() == model)
160  return;
161  if (this->model())
162  disconnect(this->model(), 0, this, 0);
163 
164  QComboBox::setModel(model);
165  reloadModel();
166 
171 }
172 
173 QModelIndex TreeComboBox::insertItem(int index, const QMap<int, QVariant> &values, const QModelIndex &parentIndex, const bool reload)
174 {
175  QModelIndex ret;
176  QModelIndex root = parentIndex;
177  if (!root.isValid())
178  root = view()->rootIndex();
179 
180  index = qBound(0, index, model()->rowCount(root));
181 
182  bool blocked = model()->signalsBlocked();
183  if (!reload)
184  model()->blockSignals(true);
185 
186  if (QStandardItemModel *m = qobject_cast<QStandardItemModel*>(model())) {
187  QStandardItem * item = new QStandardItem();
188  QMapIterator<int, QVariant> i(values);
189  while (i.hasNext()) {
190  i.next();
191  item->setData(i.value(), i.key());
192  }
193  if (root.isValid() && m->itemFromIndex(root))
194  m->itemFromIndex(root)->insertRow(index, item);
195  else
196  m->insertRow(index, item);
197  ret = item->index();
198  }
199  else if (model()->insertRows(index, 1, root)) {
200  ret = model()->index(index, modelColumn(), root);
201  if (!values.isEmpty())
202  model()->setItemData(ret, values);
203  }
204  model()->blockSignals(blocked);
205 
206  return ret;
207 }
208 
209 QModelIndex TreeComboBox::insertItem(int index, const QIcon &icon, const QString &text, const QModelIndex &parentIndex, const QVariant &userData, const bool reload)
210 {
211  QMap<int, QVariant> values;
212  if (!text.isNull())
213  values.insert(Qt::EditRole, text);
214  if (!icon.isNull())
215  values.insert(Qt::DecorationRole, icon);
216  if (userData.isValid())
217  values.insert(Qt::UserRole, userData);
218  else if (autoData())
219  values.insert(Qt::UserRole, m_nextDataId++);
220 
221  return insertItem(index, values, parentIndex, reload);
222 }
223 
224 void TreeComboBox::insertItems(int index, const QStringList &texts, const QModelIndex &parentIndex)
225 {
226  for (const QString &text : texts)
227  insertItem(index++, QIcon(), text, parentIndex, QVariant(), (text == texts.last()));
228 }
229 
230 QModelIndex TreeComboBox::insertParentItem(int index, const QIcon &icon, const QString &text, const bool selectable, const QModelIndex &parentIndex, const QVariant &userData)
231 {
232  bool oldAuto = autoData();
233  m_autoData = selectable;
234  QModelIndex idx = insertItem(index, icon, text, parentIndex, userData);
235  m_autoData = oldAuto;
236  TreeComboItemDelegate::setParent(model(), idx, selectable);
237  return idx;
238 }
239 
241 {
242  setModel(new QStandardItemModel(0, 1, this));
243 }
244 
246 {
248  return m_rowMap.value(view()->currentIndex());
249 
250  return -1;
251 }
252 
254 {
256 }
257 
259 {
260  //qDebug() << index << m_currentIndex;
261  if (!index.isValid() || !(index.flags() & Qt::ItemIsSelectable)) {
264  return;
265  }
266  const QModelIndex & root = view()->rootIndex(); // save actual root
267  const bool blocked = blockSignals(true); // we handle all signals
268  setRootModelIndex(model()->parent(index)); // set dummy root so that row() sets correct item under parent (if any)
270  setRootModelIndex(root); // reset so that full tree is visible again
271  blockSignals(blocked);
272 
273  // set view index after QComboBox::setCurrentIndex call
274  view()->setCurrentIndex(index);
275 
276  if (m_currentIndex == index)
277  return;
278 
280  // We handle all signals ourselves because QComboBox doesn't always detect change between parent rows (eg. parentA.row0 and parentB.row0)
281  const QString text = model()->data(index).toString();
282  const QVariant currData = currentData();
283  emit currentIndexChanged(m_rowMap.value(index));
284  emit currentIndexChanged(text);
285  emit currentModelIndexChanged(index);
286  if (!isEditable())
287  emit currentTextChanged(text);
288  if (currData.isValid())
289  emit currentDataChanged(currData);
290 #ifndef QT_NO_ACCESSIBILITY
293 #endif
294 }
295 
296 int TreeComboBox::setCurrentData(const QVariant &data, const int defaultIdx, int role, Qt::MatchFlags flags)
297 {
298  int idx = findData(data, role, flags);
299  if (idx == -1)
300  idx = defaultIdx;
301  setCurrentIndex(idx);
302  return idx;
303 }
304 
306 {
307  return model()->data(view()->currentIndex(), role);
308 }
309 
310 QVariant TreeComboBox::itemData(int index, int role) const
311 {
312  if (m_indexMap.contains(index))
313  return model()->data(m_indexMap.value(index), role);
314 
315  return QVariant();
316 }
317 
319 {
320  QVariant decoration = itemData(index, Qt::DecorationRole);
321  if (decoration.type() == QVariant::Pixmap)
322  return QIcon(qvariant_cast<QPixmap>(decoration));
323  else if (decoration.type() == QVariant::Icon)
324  return qvariant_cast<QIcon>(decoration);
325  else
326  return QIcon();
327 }
328 
329 void TreeComboBox::setItemData(const QModelIndex & index, const QVariant & value, int role)
330 {
331  if (index.isValid())
332  model()->setData(index, value, role);
333 }
334 
335 int TreeComboBox::findData(const QVariant &data, int role, Qt::MatchFlags flags) const
336 {
337  const QModelIndex & mi = model()->index(0, modelColumn(), view()->rootIndex());
338  QModelIndexList result = model()->match(mi, role, data, -1, (flags | Qt::MatchRecursive));
339  while (!result.isEmpty()) {
340  const QModelIndex i = result.takeFirst();
341  if ((i.flags() & Qt::ItemIsSelectable) && m_rowMap.contains(i))
342  return m_rowMap.value(i);
343  }
344 
345  return -1;
346 }
347 
349 {
350  do {
351  index = view()->indexAbove(index);
352  if (model()->hasChildren(index) && !view()->isExpanded(index)) {
353  view()->setExpanded(index, true);
354  index = lastIndex(index);
355  }
356  } while (index.isValid() && !(model()->flags(index) & Qt::ItemIsSelectable));
357  return index;
358 }
359 
361 {
362  do {
363  if (model()->hasChildren(index))
364  view()->setExpanded(index, true);
365  index = view()->indexBelow(index);
366  } while (index.isValid() && !(model()->flags(index) & Qt::ItemIsSelectable));
367  return index;
368 }
369 
371 {
372  if (index.isValid() && !view()->isExpanded(index))
373  return index;
374  int rows = view()->model()->rowCount(index);
375  if (rows == 0)
376  return index;
377  return lastIndex(view()->model()->index(rows - 1, modelColumn(), index));
378 }
379 
381 {
382  view()->keyboardSearch(text);
383  QModelIndex index = view()->currentIndex();
384  if (index.isValid() && !(model()->flags(index) & Qt::ItemIsSelectable))
385  index = indexBelow(index);
386  //qDebug() << index;
387  if (index.isValid())
388  setCurrentIndex(index);
389 }
390 
392 {
393  QModelIndex index = m_view->currentIndex();
394  if (event->delta() > 0)
395  index = indexAbove(index);
396  else if (event->delta() < 0)
397  index = indexBelow(index);
398 
399  event->accept();
400  if (!index.isValid())
401  return;
402 
403  setCurrentIndex(index);
404  emit activated(m_rowMap.value(index));
405 }
406 
408 {
409  if (isEditable() || (event->modifiers() & Qt::ControlModifier)) {
411  return; // pass to line edit
412  }
413 
414  QModelIndex index = m_view->currentIndex();
415  switch (event->key()) {
416  case Qt::Key_Up:
417  case Qt::Key_PageUp:
418  index = indexAbove(index);
419  break;
420  case Qt::Key_Down:
421  case Qt::Key_PageDown:
422  if (event->modifiers() & Qt::AltModifier) {
423  showPopup();
424  return;
425  }
426  index = indexBelow(index);
427  break;
428  case Qt::Key_Home:
429  index = m_view->model()->index(0, modelColumn());
430  if (index.isValid() && !(model()->flags(index) & Qt::ItemIsSelectable))
431  index = indexBelow(index);
432  break;
433  case Qt::Key_End:
434  index = lastIndex(m_view->rootIndex());
435  if (index.isValid() && !(model()->flags(index) & Qt::ItemIsSelectable))
436  index = indexAbove(index);
437  break;
438 
439  case Qt::Key_F4:
440  case Qt::Key_Space:
441  case Qt::Key_Enter:
442  case Qt::Key_Return:
443  case Qt::Key_Escape:
444  case Qt::Key_Select:
445  case Qt::Key_Left:
446  case Qt::Key_Right:
447  case Qt::Key_Back:
449  return;
450 
451  default:
452  if (!event->text().isEmpty())
453  keyboardSearchString(event->text());
454  else
455  event->ignore();
456  return;
457  }
458  if (index.isValid()) {
459  setCurrentIndex(index);
460  event->accept();
461  }
462 }
463 
465 {
466  if (object == view()->viewport()) {
467  if (event->type() == QEvent::MouseButtonRelease) {
468  // mouse release filter to keep combo box open when expanding/collapsing groups
469  m_skipNextHide = false;
470  QMouseEvent * mouseEvent = static_cast<QMouseEvent *>(event);
471  const QModelIndex index = view()->indexAt(mouseEvent->pos());
472  if (!index.isValid())
473  return false;\
474  if (!view()->visualRect(index).contains(mouseEvent->pos()) || !(index.flags() & Qt::ItemIsSelectable)) {
475  // do not hide popup if clicking on expander icon or a non-selectable item
476  m_skipNextHide = true;
477  if (model()->hasChildren(index) && view()->visualRect(index).contains(mouseEvent->pos())) {
478  // toggle expanded state if clicking on parent label
479  view()->setExpanded(index, !view()->isExpanded(index));
480  }
481  return true;
482  }
483  }
484  else if (event->type() == QEvent::MouseMove) {
485  // prevent QComboBox filter which auto-selects any item under the cursor
486  return true;
487  }
488  }
489  else if (object == view()) {
490  if (event->type() == QEvent::ShortcutOverride) {
491  // override handling of keyboard selection events within tree view
492  QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
493  const QModelIndex & index = view()->currentIndex();
494 
495  switch (keyEvent->key()) {
496  case Qt::Key_Enter:
497  case Qt::Key_Return:
498  case Qt::Key_Select:
499  if (!index.isValid())
500  break;
501  if (model()->hasChildren(index) && !(index.flags() & Qt::ItemIsSelectable)) {
502  m_skipNextHide = true;
503  view()->setExpanded(index, !view()->isExpanded(index));
504  }
505  else {
506  m_skipNextHide = false;
507  setCurrentIndex(index);
508  hidePopup();
509  }
510  return true;
511 
512  default:
513  break;
514  }
515  }
516  }
517  return false;
518 }
519 
524 }
525 
527 {
528  if (m_skipNextHide)
529  m_skipNextHide = false;
530  else
532 }
533 
535 {
536  if (!row) {
537  m_rowMap.clear();
538  m_indexMap.clear();
539  }
540  int rows = model()->rowCount(parent);
541  for (int r=0; r < rows; ++r) {
542  QPersistentModelIndex index = model()->index(r, 0, parent);
543  if (index.flags() & Qt::ItemIsSelectable) {
544  m_rowMap.insert(index, row);
545  m_indexMap.insert(row, index);
546  ++row;
547  }
548  if (model()->hasChildren(index))
549  row = buildMap(index, row);
550  }
551  return row;
552 }
553 
555 {
556  buildMap();
558 
559  // simplify the tree view for flat models, or if only one parent item
560  QModelIndexList parents;
561  int rows = model()->rowCount();
562  for (int r=0; r < rows; ++r) {
563  QModelIndex index = model()->index(r, modelColumn());
564  if (model()->hasChildren(index)) {
565  parents << index;
566  if (parents.size() > 1)
567  break;
568  }
569  }
570  if (!parents.size()) {
571  // if no parents then remove space for arrows
572  view()->setRootIsDecorated(false);
573  }
574  else if (parents.size() == 1 && parents.first() == model()->index(0, modelColumn())) {
575  // if only one parent then set it as root
576  view()->setRootIndex(parents.first());
577  }
578  else {
579  view()->setRootIndex(model()->index(-1, modelColumn()));
580  view()->setRootIsDecorated(true);
581  }
582 
583  // set minium width based on tree view width
586  setMinimumWidth(view()->minimumWidth() + 16);
587 }
588 
590 {
592  if (p.isValid() && !view()->isExpanded(p)) {
593  bool blocked = view()->blockSignals(true);
594  view()->setExpanded(p, true);
595  view()->blockSignals(blocked);
596  }
597 }
598 
600 {
602  initStyleOption(&opt);
603  if (option)
604  *option = opt;
605  return style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this);
606 }
607 
609 {
610  if (qobject_cast<TreeComboBoxView *>(view())) {
611  qobject_cast<TreeComboBoxView *>(view())->adjustWidth(topLevelWidget()->geometry().width());
612  }
613  else {
616  view()->setMinimumWidth(view()->minimumSizeHint().width() + view()->verticalScrollBar()->sizeHint().width() + view()->indentation());
617  }
618 }
619 
621 {
623  const bool usePopup = this->usePopup(&opt);
624  if (!(opt.state & QStyle::State_On))
625  return; // popup is hidden
626 
627  const bool boundToScreen = !window()->testAttribute(Qt::WA_DontShowOnScreen);
629  const int viewH = view()->sizeHint().height();
630  QWidget * container = view()->parentWidget();
631  QRect listRect = container->geometry(); // QComboBox sets geometry on it's private container to control the selector view size
632 
633  // set desired adjustment (delta) size
634  int adjH = viewH - listRect.size().height();
635  //qDebug() << "listRect" << listRect << "adjH" << adjH << "viewH" << viewH << "screen" << screen << "popup" << usePopup << "bound" << boundToScreen;
636  if (!adjH)
637  return;
638 
639  const int algnTop = parentWidget()->mapToGlobal(frameGeometry().topLeft()).y();
640  const int algnBot = parentWidget()->mapToGlobal(frameGeometry().bottomLeft()).y();
641  const int aboveHeight = algnTop - screen.y();
642  const int belowHeight = screen.bottom() - algnBot;
643 
644  if (usePopup)
645  adjH += 15; // otherwise scroll buttons cover up list items (better way?)
646  else
647  adjH += 3; // for scroll margin (otherwise vert. scrollbar appears when not needed)
648 
649  // resize the tree viewport
650  listRect.adjust(0, 0, 0, adjH);
651  //qDebug() << "listRect" << listRect << "adjH" << adjH << "algnTop" << algnTop << "aboveH" << aboveHeight << "algnBot" << algnBot << "belowH" << belowHeight;
652 
653  // takes into account the container size restraints
654  listRect.setSize(listRect.size().expandedTo(container->minimumSize()).boundedTo(container->maximumSize()));
655  // make sure the widget fits and visible on screen vertically
656  if (usePopup) {
657  // Clamp the listRect height and vertical position so we don't expand outside the available screen geometry.
658  const int height = !boundToScreen ? listRect.height() : qMin(listRect.height(), screen.height());
659  listRect.setHeight(height);
660  if (listRect.bottom() < algnTop)
661  listRect.moveBottom(algnTop); // don't leave a short list hanging above the selector widget
662  if (boundToScreen) {
663  // make sure full list is visible
664  if (listRect.top() < screen.top())
665  listRect.moveTop(screen.top());
666  if (listRect.bottom() > screen.bottom())
667  listRect.moveBottom(screen.bottom());
668  }
669  }
670  else {
671  // constrain to maximum visible items size
672  QRect visReg = view()->visualRect(view()->currentIndex());
673  // get the height of one item in the view (better way?)
674  int maxH = (visReg.isValid() ? visReg.size().height() : view()->fontMetrics().boundingRect('A').height()) * maxVisibleItems();
675  listRect.setHeight(qMin(listRect.height(), maxH));
676 
677  if (!boundToScreen || listRect.height() > aboveHeight) {
678  // move under selector widget
679  if (boundToScreen && belowHeight < listRect.height())
680  listRect.setHeight(belowHeight);
681  listRect.moveTop(algnBot);
682  }
683  else if (listRect.height() > belowHeight || listRect.bottom() < algnTop || (listRect.bottom() > algnTop && listRect.top() < algnTop)) {
684  // move above selector widget
685  if (aboveHeight < listRect.height())
686  listRect.setHeight(aboveHeight);
687  listRect.moveBottom(algnTop);
688  }
689  }
690  //qDebug() << "listRect" << listRect;
691 
692  container->setGeometry(listRect);
693 }
void adjustPopupHeight()
Resize visible popup height when items are expanded/collapsed in the tree view.
void initStyleOption(QStyleOptionComboBox *option) const const
void moveBottom(int y)
void setView(QAbstractItemView *itemView)
virtual int rowCount(const QModelIndex &parent) const const=0
An item rendering delegate to highlight parent items and draw better item separators.
Definition: TreeComboBox.h:50
ControlModifier
MouseButtonRelease
QSize size() const const
QModelIndex indexBelow(QModelIndex index)
Find first valid item index which if after given index.
QAbstractItemModel * model() const const
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
QModelIndex lastIndex(const QModelIndex &index)
Find last (greatest) valid item index in a set (eg.
QTreeView subclass used to display the combo box popup items.
Definition: TreeComboBox.h:255
bool contains(const Key &key) const const
void setCurrentIndex(const QModelIndex &index)
typedef MatchFlags
void setRenderHint(QPainter::RenderHint hint, bool on)
void setWordWrap(bool on)
QTreeView * m_view
Definition: TreeComboBox.h:239
QWidget * window() const const
void setView(QAbstractItemView *itemView=Q_NULLPTR)
Like QComboBox::setView but only accepts QTreeView (and derived) view classes.
QStyle * style() const const
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
void setItemDelegate(QAbstractItemDelegate *delegate)
void setMinimumWidth(int minw)
void collapsed(const QModelIndex &index)
QIcon itemIcon(int index) const
Reimplemented from superclass.
virtual void keyPressEvent(QKeyEvent *event) override
Reimplemented from superclass.
QPoint mapToGlobal(const QPoint &pos) const const
QModelIndex indexAbove(QModelIndex index)
Find first valid item index which if before given index.
static void setParent(QAbstractItemModel *model, const QModelIndex &index, const bool selectable=false)
void save()
virtual void keyPressEvent(QKeyEvent *e) override
SH_ComboBox_Popup
QModelIndex indexBelow(const QModelIndex &index) const const
QVariant itemData(int index, int role=Qt::UserRole) const
Reimplemented from superclass.
QWidget * viewport() const const
int height() const const
void setRootModelIndex(const QModelIndex &index)
int y() const const
virtual QRect visualRect(const QModelIndex &index) const const override
void drawLine(const QLineF &line)
bool isEditable() const const
void setSelectionBehavior(QAbstractItemView::SelectionBehavior behavior)
bool m_skipNextHide
Definition: TreeComboBox.h:245
void clear()
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QModelIndex insertItem(int index, const QMap< int, QVariant > &values=QMap< int, QVariant >(), const QModelIndex &parentIndex=QModelIndex(), const bool reload=true)
Insert an item at given index (row), with optional data values, under parent item indicated by parent...
QMap< int, QPersistentModelIndex > m_indexMap
Definition: TreeComboBox.h:241
static bool isParent(const QModelIndex &index)
virtual void keyboardSearch(const QString &search) override
virtual QSize sizeHint() const const override
int y() const const
virtual void hidePopup() override
Reimplemented from superclass.
virtual void setRootIndex(const QModelIndex &index) override
virtual void setData(const QVariant &value, int role)
const QRect & geometry() const const
bool isNull() const const
int width() const const
void clear()
Like QComboBox::clear() but does NOT remove any items from the current data model.
virtual bool setItemData(const QModelIndex &index, const QMap< int, QVariant > &roles)
virtual QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const const
void setExpanded(const QModelIndex &index, bool expanded)
virtual bool event(QEvent *event) override
Qt::ItemFlags flags() const const
int currentIndex() const
Reimplemented from superclass.
bool isValid() const const
QRect boundingRect(QChar ch) const const
void setItemData(const QModelIndex &index, const QVariant &value, int role=Qt::UserRole)
Sets the data role for the item at index to the specified value.
bool testAttribute(Qt::WidgetAttribute attribute) const const
void installEventFilter(QObject *filterObj)
QWidget * topLevelWidget() const const
virtual QSize minimumSizeHint() const const override
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector< int > &roles)
void keyboardSearchString(const QString &text)
Reimplemented from superclass.
QScreen * primaryScreen()
int top() const const
int modelColumn() const const
void resizeColumnToContents(int column)
QMapIterator::Item next()
void setPen(const QColor &color)
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const const override
virtual void hidePopup()
AccessibleDescriptionRole
QModelIndex insertParentItem(int index, const QIcon &icon, const QString &text, const bool selectable=false, const QModelIndex &parentIndex=QModelIndex(), const QVariant &userData=QVariant())
Inserts an item and marks is as a "parent" type item.
void insertItems(int index, const QStringList &texts, const QModelIndex &parentIndex)
Inserts multiple items from a list as children of parentIndex.
virtual int styleHint(QStyle::StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const const=0
void activated(int index)
int row() const const
void setWidthF(qreal width)
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const const override
virtual QVariant data(const QModelIndex &index, int role) const const=0
QRect frameGeometry() const const
void setAllColumnsShowFocus(bool enable)
static void setSeparator(QAbstractItemModel *model, const QModelIndex &index)
const Key & key() const const
void setColor(const QColor &color)
void moveTop(int y)
void rowsRemoved(const QModelIndex &parent, int first, int last)
void setIndentation(int i)
const T & value() const const
bool isExpanded(const QModelIndex &index) const const
bool signalsBlocked() const const
QTreeView * view() const
Definition: TreeComboBox.h:104
TreeComboBox(QWidget *parent=Q_NULLPTR)
virtual QModelIndex parent(const QModelIndex &index) const const=0
int key() const const
bool blockSignals(bool block)
void currentTextChanged(const QString &text)
bool isValid() const const
QModelIndex rootIndex() const const
void reloadModel()
void restore()
QVariant currentData(int role=Qt::UserRole) const
Reimplemented from superclass.
bool autoData() const
Definition: TreeComboBox.h:105
WA_DontShowOnScreen
void ensureCurrentExpanded()
Called before showing popup to make sure the initial view size is correct.
bool contains(const QRect &rectangle, bool proper) const const
bool usePopup(QStyleOptionComboBox *option=NULL)
Return true if style options are set to use a "popup" presentation style (typ.
static bool isSeparator(const QModelIndex &index)
void setMaximumWidth(int maxw)
QFontMetrics fontMetrics() const const
QVariant data(int role) const const
int findData(const QVariant &data, int role=Qt::UserRole, Qt::MatchFlags flags=Qt::MatchFlags(Qt::MatchExactly|Qt::MatchCaseSensitive)) const
Reimplemented from superclass.
void setModel(QAbstractItemModel *model)
QSize expandedTo(const QSize &otherSize) const const
void setHeaderHidden(bool hide)
virtual bool hasChildren(const QModelIndex &parent) const const
virtual void wheelEvent(QWheelEvent *event) override
Reimplemented from superclass.
bool isNull() const const
void setHeight(int height)
QWidget * parentWidget() const const
int height() const const
void adjustPopupWidth()
Make sure tree view has a reasonable width.
void setModel(QAbstractItemModel *model)
Reimplemented from superclass.
void adjust(int dx1, int dy1, int dx2, int dy2)
int bottom() const const
void setCurrentIndex(int index)
void setSizeAdjustPolicy(QAbstractScrollArea::SizeAdjustPolicy policy)
QModelIndex index() const const
virtual bool setData(const QModelIndex &index, const QVariant &value, int role)
int buildMap(QModelIndex parent=QModelIndex(), int row=0)
Emitted along with currentIndexChanged() signals and if item has valid Qt::UserRole data.
void currentModelIndexChanged(const QModelIndex &index)
QString fromLatin1(const char *str, int size)
bool isValid() const const
virtual Qt::ItemFlags flags(const QModelIndex &index) const const
Qt::ItemFlags flags() const const
QMap< QPersistentModelIndex, int > m_rowMap
Definition: TreeComboBox.h:240
QMap::iterator insert(const Key &key, const T &value)
bool isEmpty() const const
void expanded(const QModelIndex &index)
QPoint pos() const const
virtual void showPopup() override
Reimplemented from superclass.
int setCurrentData(const QVariant &data, const int defaultIdx=-1, int role=Qt::UserRole, Qt::MatchFlags flags=Qt::MatchFlags(Qt::MatchExactly|Qt::MatchCaseSensitive))
This is a shortcut to using setCurrentIndex(findData()), and also returns the new index (like findDat...
QAbstractItemModel * model() const const
QVariant::Type type() const const
QPersistentModelIndex m_currentIndex
Definition: TreeComboBox.h:242
QModelIndex currentIndex() const const
void rowsInserted(const QModelIndex &parent, int first, int last)
void setRootIsDecorated(bool show)
void setCurrentIndex(int index)
Reimplemented from superclass.
void setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy policy)
HighQualityAntialiasing
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
void updateAccessibility(QObject *object, int child, QAccessible::Event reason)
void setSize(const QSize &size)
void setMaxVisibleItems(int maxItems)
virtual void showPopup()
const QPen & pen() const const
QString toString() const const
void setItemsExpandable(bool enable)
QModelIndex indexAbove(const QModelIndex &index) const const
int size() const const
virtual QSize sizeHint() const const override
void removeEventFilter(QObject *obj)
int height() const const
virtual QModelIndex indexAt(const QPoint &point) const const override
void currentIndexChanged(int index)
bool hasNext() const const
void setGeometry(int x, int y, int w, int h)
const T value(const Key &key, const T &defaultValue) const const
void currentDataChanged(const QVariant &data)
ItemIsSelectable
virtual bool eventFilter(QObject *object, QEvent *event) override
Reimplemented from superclass.