ctkTreeComboBox.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) 2010 Kitware Inc.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.commontk.org/LICENSE
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. =========================================================================*/
  14. // Qt includes
  15. #include <QEvent>
  16. #include <QMouseEvent>
  17. #include <QModelIndex>
  18. #include <QTreeView>
  19. #include <QDebug>
  20. // CTK includes
  21. #include "ctkTreeComboBox.h"
  22. // -------------------------------------------------------------------------
  23. class ctkTreeComboBoxPrivate: public ctkPrivate<ctkTreeComboBox>
  24. {
  25. public:
  26. bool SkipNextHide;
  27. bool ResetPopupSize;
  28. void init()
  29. {
  30. this->SkipNextHide = false;
  31. this->ResetPopupSize = false;
  32. }
  33. };
  34. // -------------------------------------------------------------------------
  35. ctkTreeComboBox::ctkTreeComboBox(QWidget* _parent):Superclass(_parent)
  36. {
  37. CTK_INIT_PRIVATE(ctkTreeComboBox);
  38. CTK_D(ctkTreeComboBox);
  39. d->init();
  40. QTreeView* treeView = new QTreeView(this);
  41. treeView->setHeaderHidden(true);
  42. this->setView(treeView);
  43. // we install the filter AFTER the QComboBox installed it.
  44. // so that our eventFilter will be called first
  45. this->view()->viewport()->installEventFilter(this);
  46. connect(treeView, SIGNAL(collapsed(const QModelIndex&)),
  47. this, SLOT(onCollapsed(const QModelIndex&)));
  48. connect(treeView, SIGNAL(expanded(const QModelIndex&)),
  49. this, SLOT(onExpanded(const QModelIndex&)));
  50. }
  51. // -------------------------------------------------------------------------
  52. bool ctkTreeComboBox::eventFilter(QObject* object, QEvent* _event)
  53. {
  54. CTK_D(ctkTreeComboBox);
  55. bool res = false;
  56. if (_event->type() == QEvent::MouseButtonRelease &&
  57. object == this->view()->viewport())
  58. {
  59. QMouseEvent* mouseEvent = dynamic_cast<QMouseEvent*>(_event);
  60. QModelIndex index = this->view()->indexAt(mouseEvent->pos());
  61. // do we click the branch (+ or -) or the item itself ?
  62. if (this->view()->model()->hasChildren(index) &&
  63. (index.flags() & Qt::ItemIsSelectable) &&
  64. !this->view()->visualRect(index).contains(mouseEvent->pos()))
  65. {//qDebug() << "Set skip on";
  66. // if the branch is clicked, then we don't want to close the
  67. // popup. (we don't want to select the item, just expand it.)
  68. // of course, all that doesn't apply with unselectable items, as
  69. // they won't close the popup.
  70. d->SkipNextHide = true;
  71. }
  72. // we want to get rid of an odd behavior.
  73. // If the user highlight a selectable item and then
  74. // click on the branch of an unselectable item while keeping the
  75. // previous selection. The popup would be normally closed in that
  76. // case. We don't want that.
  77. if ( this->view()->model()->hasChildren(index) &&
  78. !(index.flags() & Qt::ItemIsSelectable) &&
  79. !this->view()->visualRect(index).contains(mouseEvent->pos()))
  80. {//qDebug() << "eat";
  81. // eat the event, don't go to the QComboBox event filters.
  82. res = true;
  83. }
  84. if (d->ResetPopupSize)
  85. {
  86. d->ResetPopupSize = false;
  87. //this->QComboBox::showPopup();
  88. }
  89. }
  90. return res;
  91. }
  92. // -------------------------------------------------------------------------
  93. void ctkTreeComboBox::showPopup()
  94. {
  95. this->setRootModelIndex(QModelIndex());
  96. this->QComboBox::showPopup();
  97. }
  98. // -------------------------------------------------------------------------
  99. void ctkTreeComboBox::hidePopup()
  100. {
  101. CTK_D(ctkTreeComboBox);
  102. if (d->SkipNextHide)
  103. {// don't hide the popup if the selected item is a parent.
  104. d->SkipNextHide = false;
  105. //this->setCurrentIndex(-1);
  106. //qDebug() << "skip";
  107. //this->QComboBox::showPopup();
  108. }
  109. else
  110. {
  111. QModelIndex _currentIndex = this->view()->currentIndex();
  112. //qDebug() << "ctkTreeComboBox::hidePopup() " << _currentIndex << " " << _currentIndex.row();
  113. //qDebug() << "before: " << this->currentIndex() << this->view()->currentIndex();
  114. this->QComboBox::hidePopup();
  115. //qDebug() << "after: " << this->currentIndex() << this->view()->currentIndex();
  116. this->setRootModelIndex(_currentIndex.parent());
  117. this->setCurrentIndex(_currentIndex.row());
  118. //qDebug() << "after2: " << this->currentIndex() << this->view()->currentIndex();
  119. }
  120. }
  121. // -------------------------------------------------------------------------
  122. void ctkTreeComboBox::onCollapsed(const QModelIndex& index)
  123. {
  124. CTK_D(ctkTreeComboBox);
  125. if (this->view()->currentIndex().parent() == index)
  126. {
  127. // in the case the current item is a child of the collapsed/expanded item.
  128. // we don't want to resize the popup as it would undo the collapsed item.
  129. return;
  130. }
  131. d->ResetPopupSize = true;
  132. }
  133. // -------------------------------------------------------------------------
  134. void ctkTreeComboBox::onExpanded(const QModelIndex& /*index*/)
  135. {
  136. ctk_d()->ResetPopupSize = true;
  137. }
  138. // -------------------------------------------------------------------------
  139. void ctkTreeComboBox::paintEvent(QPaintEvent *p)
  140. {
  141. //qDebug() << __FUNCTION__ << " " << this->currentText() << " " << this->currentIndex() ;
  142. //qDebug() << this->itemText(0) << this->itemText(1);
  143. this->QComboBox::paintEvent(p);
  144. }