ctkTreeComboBox.cpp

Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Library:   CTK
00004  
00005   Copyright (c) 2010  Kitware Inc.
00006 
00007   Licensed under the Apache License, Version 2.0 (the "License");
00008   you may not use this file except in compliance with the License.
00009   You may obtain a copy of the License at
00010 
00011       http://www.commontk.org/LICENSE
00012 
00013   Unless required by applicable law or agreed to in writing, software
00014   distributed under the License is distributed on an "AS IS" BASIS,
00015   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016   See the License for the specific language governing permissions and
00017   limitations under the License.
00018  
00019 =========================================================================*/
00020 
00021 // Qt includes
00022 #include <QEvent>
00023 #include <QMouseEvent>
00024 #include <QModelIndex>
00025 #include <QTreeView>
00026 #include <QDebug>
00027 
00028 // CTK includes
00029 #include "ctkTreeComboBox.h"
00030 
00031 // -------------------------------------------------------------------------
00032 class ctkTreeComboBoxPrivate: public ctkPrivate<ctkTreeComboBox>
00033 {
00034 public:
00035   bool SkipNextHide;
00036   bool ResetPopupSize;
00037   
00038   void init()
00039   {
00040     this->SkipNextHide = false;
00041     this->ResetPopupSize = false;
00042   }
00043 };
00044 
00045 // -------------------------------------------------------------------------
00046 ctkTreeComboBox::ctkTreeComboBox(QWidget* _parent):Superclass(_parent)
00047 {
00048   CTK_INIT_PRIVATE(ctkTreeComboBox);
00049   CTK_D(ctkTreeComboBox);
00050   
00051   d->init();
00052   QTreeView* treeView = new QTreeView(this);
00053   treeView->setHeaderHidden(true);
00054   this->setView(treeView);
00055   // we install the filter AFTER the QComboBox installed it.
00056   // so that our eventFilter will be called first
00057   this->view()->viewport()->installEventFilter(this);
00058   connect(treeView, SIGNAL(collapsed(const QModelIndex&)),
00059           this, SLOT(onCollapsed(const QModelIndex&)));
00060   connect(treeView, SIGNAL(expanded(const QModelIndex&)),
00061           this, SLOT(onExpanded(const QModelIndex&)));
00062 }
00063 
00064 // -------------------------------------------------------------------------
00065 bool ctkTreeComboBox::eventFilter(QObject* object, QEvent* _event)
00066 {
00067   CTK_D(ctkTreeComboBox);
00068   
00069   bool res = false;
00070   if (_event->type() == QEvent::MouseButtonRelease && 
00071       object == this->view()->viewport())
00072     {
00073     QMouseEvent* mouseEvent = dynamic_cast<QMouseEvent*>(_event); 
00074     QModelIndex index = this->view()->indexAt(mouseEvent->pos());
00075     // do we click the branch (+ or -) or the item itself ?
00076     if (this->view()->model()->hasChildren(index) && 
00077         (index.flags() & Qt::ItemIsSelectable) &&
00078         !this->view()->visualRect(index).contains(mouseEvent->pos()))
00079       {//qDebug() << "Set skip on";
00080       // if the branch is clicked, then we don't want to close the 
00081       // popup. (we don't want to select the item, just expand it.)
00082       // of course, all that doesn't apply with unselectable items, as
00083       // they won't close the popup.
00084       d->SkipNextHide = true;
00085       }
00086 
00087     // we want to get rid of an odd behavior. 
00088     // If the user highlight a selectable item and then 
00089     // click on the branch of an unselectable item while keeping the 
00090     // previous selection. The popup would be normally closed in that
00091     // case. We don't want that.
00092     if ( this->view()->model()->hasChildren(index) && 
00093         !(index.flags() & Qt::ItemIsSelectable) &&         
00094         !this->view()->visualRect(index).contains(mouseEvent->pos()))
00095       {//qDebug() << "eat";
00096       // eat the event, don't go to the QComboBox event filters.
00097       res = true;
00098       }
00099 
00100     if (d->ResetPopupSize)
00101       {
00102       d->ResetPopupSize = false;
00103       //this->QComboBox::showPopup();
00104       }
00105     }
00106   return res;
00107 }
00108 
00109 // -------------------------------------------------------------------------
00110 void ctkTreeComboBox::showPopup()
00111 {
00112   this->setRootModelIndex(QModelIndex());
00113   this->QComboBox::showPopup();
00114 }
00115 
00116 // -------------------------------------------------------------------------
00117 void ctkTreeComboBox::hidePopup()
00118 {
00119   CTK_D(ctkTreeComboBox);
00120   
00121   if (d->SkipNextHide)
00122     {// don't hide the popup if the selected item is a parent.
00123     d->SkipNextHide = false;
00124     //this->setCurrentIndex(-1);
00125     //qDebug() << "skip";
00126     //this->QComboBox::showPopup();
00127     }
00128   else
00129     {
00130     QModelIndex _currentIndex = this->view()->currentIndex();
00131     //qDebug() << "ctkTreeComboBox::hidePopup() " << _currentIndex << " " << _currentIndex.row();
00132     //qDebug() << "before: " << this->currentIndex() << this->view()->currentIndex();
00133     this->QComboBox::hidePopup();
00134     //qDebug() << "after: " << this->currentIndex() << this->view()->currentIndex();
00135     this->setRootModelIndex(_currentIndex.parent());
00136     this->setCurrentIndex(_currentIndex.row());
00137     //qDebug() << "after2: " << this->currentIndex() << this->view()->currentIndex();
00138     }
00139 }
00140 
00141 // -------------------------------------------------------------------------
00142 void ctkTreeComboBox::onCollapsed(const QModelIndex& index)
00143 {
00144   CTK_D(ctkTreeComboBox);
00145   
00146   if (this->view()->currentIndex().parent() == index)
00147     {
00148     // in the case the current item is a child of the collapsed/expanded item.
00149     // we don't want to resize the popup as it would undo the collapsed item.
00150     return;
00151     }
00152   d->ResetPopupSize = true;
00153 }
00154 
00155 // -------------------------------------------------------------------------
00156 void ctkTreeComboBox::onExpanded(const QModelIndex& /*index*/)
00157 {
00158   ctk_d()->ResetPopupSize = true;
00159 }
00160 
00161 // -------------------------------------------------------------------------
00162 void ctkTreeComboBox::paintEvent(QPaintEvent *p)
00163 {
00164   //qDebug() << __FUNCTION__ << " " << this->currentText() << " " << this->currentIndex() ;
00165   //qDebug() << this->itemText(0) << this->itemText(1);
00166   this->QComboBox::paintEvent(p);
00167 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines