| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 | /*=========================================================================  Library:   CTK  Copyright (c) Kitware Inc.   All rights reserved.  Distributed under a BSD License. See LICENSE.txt file.  This software is distributed "AS IS" WITHOUT ANY WARRANTY; without even  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the above copyright notice for more information.=========================================================================*/// Qt includes#include <QEvent>#include <QMouseEvent>#include <QModelIndex>#include <QTreeView>#include <QDebug>// CTK includes#include "ctkTreeComboBox.h"// -------------------------------------------------------------------------class ctkTreeComboBoxPrivate: public ctkPrivate<ctkTreeComboBox>{public:  bool SkipNextHide;  bool ResetPopupSize;    void init()  {    this->SkipNextHide = false;    this->ResetPopupSize = false;  }};// -------------------------------------------------------------------------ctkTreeComboBox::ctkTreeComboBox(QWidget* _parent):Superclass(_parent){  CTK_INIT_PRIVATE(ctkTreeComboBox);  CTK_D(ctkTreeComboBox);    d->init();  QTreeView* treeView = new QTreeView(this);  treeView->setHeaderHidden(true);  this->setView(treeView);  // we install the filter AFTER the QComboBox installed it.  // so that our eventFilter will be called first  this->view()->viewport()->installEventFilter(this);  connect(treeView, SIGNAL(collapsed(const QModelIndex&)),          this, SLOT(onCollapsed(const QModelIndex&)));  connect(treeView, SIGNAL(expanded(const QModelIndex&)),          this, SLOT(onExpanded(const QModelIndex&)));}// -------------------------------------------------------------------------bool ctkTreeComboBox::eventFilter(QObject* object, QEvent* _event){  CTK_D(ctkTreeComboBox);    bool res = false;  if (_event->type() == QEvent::MouseButtonRelease &&       object == this->view()->viewport())    {    QMouseEvent* mouseEvent = dynamic_cast<QMouseEvent*>(_event);     QModelIndex index = this->view()->indexAt(mouseEvent->pos());    // do we click the branch (+ or -) or the item itself ?    if (this->view()->model()->hasChildren(index) &&         (index.flags() & Qt::ItemIsSelectable) &&        !this->view()->visualRect(index).contains(mouseEvent->pos()))      {//qDebug() << "Set skip on";      // if the branch is clicked, then we don't want to close the       // popup. (we don't want to select the item, just expand it.)      // of course, all that doesn't apply with unselectable items, as      // they won't close the popup.      d->SkipNextHide = true;      }    // we want to get rid of an odd behavior.     // If the user highlight a selectable item and then     // click on the branch of an unselectable item while keeping the     // previous selection. The popup would be normally closed in that    // case. We don't want that.    if ( this->view()->model()->hasChildren(index) &&         !(index.flags() & Qt::ItemIsSelectable) &&                 !this->view()->visualRect(index).contains(mouseEvent->pos()))      {//qDebug() << "eat";      // eat the event, don't go to the QComboBox event filters.      res = true;      }    if (d->ResetPopupSize)      {      d->ResetPopupSize = false;      //this->QComboBox::showPopup();      }    }  return res;}// -------------------------------------------------------------------------void ctkTreeComboBox::showPopup(){  this->setRootModelIndex(QModelIndex());  this->QComboBox::showPopup();}// -------------------------------------------------------------------------void ctkTreeComboBox::hidePopup(){  CTK_D(ctkTreeComboBox);    if (d->SkipNextHide)    {// don't hide the popup if the selected item is a parent.    d->SkipNextHide = false;    //this->setCurrentIndex(-1);    //qDebug() << "skip";    //this->QComboBox::showPopup();    }  else    {    QModelIndex _currentIndex = this->view()->currentIndex();    //qDebug() << "ctkTreeComboBox::hidePopup() " << _currentIndex << " " << _currentIndex.row();    //qDebug() << "before: " << this->currentIndex() << this->view()->currentIndex();    this->QComboBox::hidePopup();    //qDebug() << "after: " << this->currentIndex() << this->view()->currentIndex();    this->setRootModelIndex(_currentIndex.parent());    this->setCurrentIndex(_currentIndex.row());    //qDebug() << "after2: " << this->currentIndex() << this->view()->currentIndex();    }}// -------------------------------------------------------------------------void ctkTreeComboBox::onCollapsed(const QModelIndex& index){  CTK_D(ctkTreeComboBox);    if (this->view()->currentIndex().parent() == index)    {    // in the case the current item is a child of the collapsed/expanded item.    // we don't want to resize the popup as it would undo the collapsed item.    return;    }  d->ResetPopupSize = true;}// -------------------------------------------------------------------------void ctkTreeComboBox::onExpanded(const QModelIndex& /*index*/){  ctk_d()->ResetPopupSize = true;}// -------------------------------------------------------------------------void ctkTreeComboBox::paintEvent(QPaintEvent *p){  //qDebug() << __FUNCTION__ << " " << this->currentText() << " " << this->currentIndex() ;  //qDebug() << this->itemText(0) << this->itemText(1);  this->QComboBox::paintEvent(p);}
 |