Blokkal
an Extendable KDE Blogging Client
SourceForge.net Logo

checkboxdelegate.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2007 by Martin Mueller                                  *
00003  *   orvio@orvio.de                                                        *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 #include "checkboxdelegate.h"
00021 #include "checkboxdelegate.moc"
00022 
00023 #include "checkboxview.h"
00024 
00025 #include <kdebug.h>
00026 #include <klocale.h>
00027 #include <kdialog.h>
00028 
00029 #include <QPainter>
00030 #include <QModelIndex>
00031 #include <QMouseEvent>
00032 
00033 class Blokkal::Ui::CheckBoxDelegate::Private {
00034 public:
00035         Private( void ):
00036         view( 0 ) {}
00037 
00038         CheckBoxView * view;
00039 };
00040 
00041 Blokkal::Ui::CheckBoxDelegate::CheckBoxDelegate( QObject * parent ):
00042 QItemDelegate( parent ),
00043 d( new Private( ) )
00044 {}
00045 
00046 Blokkal::Ui::CheckBoxDelegate::~CheckBoxDelegate( void )
00047 {
00048         delete d;
00049 }
00050 
00051 void Blokkal::Ui::CheckBoxDelegate::setView( CheckBoxView * view )
00052 {
00053         d->view = view;
00054 }
00055 
00056 Blokkal::Ui::CheckBoxView * Blokkal::Ui::CheckBoxDelegate::view( void ) const
00057 {
00058         return d->view;
00059 }
00060 
00061 int Blokkal::Ui::CheckBoxDelegate::checkBoxSize( const QFontMetrics & metrics ) const
00062 {
00063         return metrics.height()-1;
00064 }
00065 
00066 QRect Blokkal::Ui::CheckBoxDelegate::checkBoxRect( const QStyleOptionViewItem & option, const QModelIndex & index ) const
00067 {
00068         if( !index.isValid() ) {
00069                 return QRect();
00070         }
00071 
00072         if( !index.data( Qt::CheckStateRole ).isValid() ) {
00073                 return QRect();
00074         }
00075         
00076         const int size = checkBoxSize( option.fontMetrics );
00077 
00078         QRect boxRect;
00079         if( option.direction == Qt::LeftToRight ) {
00080                 QPoint offset = option.rect.topLeft();
00081                 boxRect = QRect( offset.x(),
00082                                  offset.y() + ( ( option.fontMetrics.height() - size ) / 2 ),
00083                                  size,
00084                                  size );
00085         }
00086         else {
00087                 QPoint offset = option.rect.topRight();
00088                 boxRect = QRect( offset.x() - size,
00089                                  offset.y() + ( ( option.fontMetrics.height() - size ) / 2 ),
00090                                  size,
00091                                  size );
00092         }
00093 
00094         return boxRect;
00095 }
00096 
00097 void Blokkal::Ui::CheckBoxDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
00098 {
00099         painter->save();
00100         drawBackground( painter, option, index );
00101 
00102         QRect boxRect = checkBoxRect( option, index );
00103         if( boxRect.isValid() ) {
00104                 drawCheck( painter,
00105                            option,
00106                            boxRect,
00107                            static_cast<Qt::CheckState>( index.data( Qt::CheckStateRole ).toInt() ) );
00108         }
00109         
00110         painter->restore();     
00111 }
00112 
00113 QSize Blokkal::Ui::CheckBoxDelegate::sizeHint( const QStyleOptionViewItem & option, const QModelIndex & index ) const
00114 {
00115         QRect boxRect = checkBoxRect( option, index );
00116         if( !boxRect.isValid() ) {
00117                 return QSize(0,0);
00118         }
00119 
00120         return boxRect.size();
00121 }
00122 
00123 bool Blokkal::Ui::CheckBoxDelegate::editorEvent( QEvent * event,
00124                                                  QAbstractItemModel * model,
00125                                                  const QStyleOptionViewItem & option,
00126                                                  const QModelIndex & index)
00127 {
00128         //Code borrowed from Qt to make this method use the virtual
00129         //checkBoxRect method
00130         Q_ASSERT(event);
00131         Q_ASSERT(model);
00132 
00133    // make sure that the item is checkable
00134         Qt::ItemFlags flags = model->flags( index );
00135         if ( !(flags & Qt::ItemIsUserCheckable)
00136              || !(option.state & QStyle::State_Enabled)
00137              || !(flags & Qt::ItemIsEnabled) )
00138         {
00139                 return FALSE;
00140         }
00141         
00142         // make sure that we have a check state
00143         QVariant value = index.data(Qt::CheckStateRole);
00144         if( !value.isValid() )
00145         {
00146                 return FALSE;
00147         }
00148 
00149         // make sure that we have the right event type
00150         if ((event->type() == QEvent::MouseButtonRelease)
00151             || (event->type() == QEvent::MouseButtonDblClick))
00152         {
00153                 QRect checkRect = checkBoxRect( option, index );
00154 
00155                 if (!checkRect.contains( static_cast<QMouseEvent*>(event)->pos()) ) {
00156                         return FALSE;
00157                 }
00158 
00159                 // eat the double click events inside the check rect
00160                 if (event->type() == QEvent::MouseButtonDblClick) {
00161                         return TRUE;
00162                 }
00163         }
00164         else {
00165                 return FALSE;
00166         }
00167 
00168         const Qt::CheckState oldState = static_cast<Qt::CheckState>(value.toInt());
00169         Qt::CheckState state = oldState == Qt::Checked ? Qt::Unchecked : Qt::Checked;
00170         bool changed = model->setData( index, state, Qt::CheckStateRole );
00171         if( changed ) {
00172                 stateChanged( model, index, state );
00173         }
00174         return changed;
00175 }
00176 
00177 void Blokkal::Ui::CheckBoxDelegate::layoutPlainItem( const QStyleOptionViewItem & option,
00178         const QModelIndex & index,
00179         QRect & textRect ) const
00180 {
00181         const int height = option.fontMetrics.height();
00182         const int width = option.rect.width();
00183         const int x = option.rect.x();
00184         const int y = option.rect.y();
00185 
00186         const QRect checkBoxRect = this->checkBoxRect( option, index );
00187         textRect.setRect( x, y, width, height );
00188         if( option.direction == Qt::LeftToRight ) {
00189                 if( checkBoxRect.isValid() ) {
00190                         textRect.setLeft( checkBoxRect.right() );
00191                 }
00192         }
00193         else {
00194                 if( checkBoxRect.isValid() ) {
00195                         textRect.setRight( checkBoxRect.left() );
00196                 }
00197         }
00198 }
00199 
00200 void Blokkal::Ui::CheckBoxDelegate::stateChanged( QAbstractItemModel * model,
00201                                                   const QModelIndex & index,
00202                                                   Qt::CheckState newState )
00203 {
00204         Q_UNUSED( model );
00205         Q_UNUSED( index );
00206         Q_UNUSED( newState );
00207 }