Blokkal
an Extendable KDE Blogging Client
SourceForge.net Logo

blogdelegate.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2007 - 2008 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 "blogdelegate.h"
00021 #include "blogdelegate.moc"
00022 
00023 #include "checkboxview.h"
00024 #include "../blokkalaccount.h"
00025 #include "../blokkalblog.h"
00026 #include "../blokkalutils.h"
00027 #include "../blokkalio/categorymanager.h"
00028 
00029 #include <kdebug.h>
00030 #include <klocale.h>
00031 #include <kdialog.h>
00032 #include <kglobalsettings.h>
00033 
00034 #include <QPainter>
00035 #include <QModelIndex>
00036 #include <QApplication>
00037 
00038 class Blokkal::Ui::BlogDelegate::Private {
00039 public:
00040         Private( unsigned int displayOptions ):
00041         displayOptions( displayOptions ){}
00042 
00043         const unsigned int displayOptions;
00044 
00045         static QString blogDescription( const Blokkal::Blog * blog ) {
00046                 return i18n( "%1 (%2)",  blog->id(), blog->type() );
00047         }
00048 
00049         static QString blogCount( const Blokkal::Account * account ) {
00050                 return i18n( "(%1)", account->blogs().size() );
00051         }
00052 };
00053 
00054 Blokkal::Ui::BlogDelegate::BlogDelegate( unsigned int displayOptions ):
00055 CheckBoxDelegate(),
00056 d( new Private( displayOptions ) )
00057 {
00058 }
00059 
00060 Blokkal::Ui::BlogDelegate::~BlogDelegate( void )
00061 {
00062         delete d;
00063 }
00064 
00065 void Blokkal::Ui::BlogDelegate::paint( QPainter * painter,
00066                                        const QStyleOptionViewItem & option,
00067                                        const QModelIndex & index ) const
00068 {
00069         CheckBoxDelegate::paint( painter, option, index );
00070         painter->save();
00071 
00072         Blokkal::Account * account = dynamic_cast<Blokkal::Account*>( (QObject*) index.data().toULongLong() );
00073         if( account ) {
00074                 QRect iconRect;
00075                 QRect textRect;
00076                 QRect countRect;
00077                 layoutAccount( option, account, iconRect, textRect, countRect );
00078                 if( iconRect.isValid() ) {
00079                         if( displayOptions() & DisplayAccountStates ) {
00080                                 if( account->connectionStatus() != Account::Connecting ) {
00081                                         view()->disconnectIndex( index );
00082                                         drawDecoration( painter, option, iconRect, account->isConnected() ? account->icon().pixmap( 16 ) : Utils::fadePixmap( account->icon().pixmap( 16 ) ) );
00083                                 }
00084                                 else {
00085                                         view()->connectIndex( index, 300 );
00086                                         drawDecoration( painter,
00087                                                         option,
00088                                                         iconRect,
00089                                                         view()->toogleBlinkState( index ) ? Utils::fadePixmap( account->icon().pixmap( 16 ) ) : account->icon().pixmap( 16 ) );
00090                                 }
00091                         }
00092                         else {
00093                                 drawDecoration( painter, option, iconRect, account->icon().pixmap( 16 ) );
00094                         }
00095                 }
00096 
00097                 QStyleOptionViewItem myOption = option;
00098                 if( displayOptions() & DisplayAccountStates
00099                     && !account->isConnected() )
00100                 {
00101                         myOption.palette.setBrush( QPalette::Active, QPalette::Text,
00102                                                    myOption.palette.brush( QPalette::Disabled, QPalette::Text ) );
00103                         myOption.palette.setBrush( QPalette::Inactive, QPalette::Text,
00104                                                    myOption.palette.brush( QPalette::Disabled, QPalette::Text ) );
00105                 }
00106                 
00107                 if( textRect.isValid() ) {
00108                         drawDisplay( painter, myOption, textRect, account->id() );
00109                 }
00110 
00111                 if( countRect.isValid() ) {
00112                         QStyleOptionViewItem countOption = myOption;
00113                         countOption.font = KGlobalSettings::smallestReadableFont();
00114                         countOption.fontMetrics = QFontMetrics( countOption.font );
00115                         drawDisplay( painter, countOption, countRect, d->blogCount( account ) );
00116                 }
00117 
00118                 painter->restore();
00119                 return;
00120         }
00121         Blokkal::Blog * blog = dynamic_cast<Blokkal::Blog*>( (QObject*) index.data().toULongLong() );
00122         if( blog ) {
00123                 QString title = blog->title().isEmpty() ? blog->id() : blog->title();
00124                 QString idTypeString = d->blogDescription( blog );
00125                 QRect iconRect;
00126                 QRect textRect;
00127                 QRect infoRect;
00128                 layoutBlog( option, index, blog, iconRect, textRect, infoRect );
00129                 if( iconRect.isValid() ) {
00130                         if( displayOptions() & DisplayAccountStates
00131                             && !blog->account()->isConnected() )
00132                         {
00133                                 drawDecoration( painter, option, iconRect, Utils::fadePixmap( blog->icon().pixmap( 16 ) ) );
00134                         }
00135                         else {
00136                                 drawDecoration( painter, option, iconRect, blog->icon().pixmap( 16 ) );
00137                         }
00138                 }
00139 
00140                 QStyleOptionViewItem myOption = option;
00141                 if( displayOptions() & DisplayAccountStates
00142                     && !blog->account()->isConnected() )
00143                 {
00144                         myOption.palette.setBrush( QPalette::Active, QPalette::Text,
00145                                                    myOption.palette.brush( QPalette::Disabled, QPalette::Text ) );
00146                         myOption.palette.setBrush( QPalette::Inactive, QPalette::Text,
00147                                                    myOption.palette.brush( QPalette::Disabled, QPalette::Text ) );
00148                 }               
00149                 
00150                 if( textRect.isValid() ) {
00151                         drawDisplay( painter, myOption, textRect, title );
00152                 }
00153                 
00154                 if( infoRect.isValid() ) {
00155                         QStyleOptionViewItem infoOption = myOption;
00156                         infoOption.font = KGlobalSettings::smallestReadableFont();
00157                         infoOption.fontMetrics = QFontMetrics( infoOption.font );
00158                         drawDisplay( painter, infoOption, infoRect, idTypeString );
00159                 }
00160 
00161                 painter->restore();
00162                 return;
00163         }
00164 
00165         Blokkal::Io::Category * category = dynamic_cast<Blokkal::Io::Category*>( (QObject*) index.data().toULongLong() );
00166         if( category ) {
00167                 QRect textRect;
00168                 layoutPlainItem( option, index, textRect );
00169                 if( textRect.isValid() ) {
00170                         drawDisplay( painter, option, textRect, category->name() );
00171                 }               
00172 
00173                 painter->restore();
00174                 return;
00175         }
00176 
00177         painter->restore();
00178 }
00179 
00180 QSize Blokkal::Ui::BlogDelegate::sizeHint( const QStyleOptionViewItem & option,
00181                                            const QModelIndex & index ) const
00182 {
00183         Blokkal::Account * account = dynamic_cast<Blokkal::Account*>( (QObject*) index.data().toULongLong() );
00184         if( account ) {
00185                 QRect iconRect;
00186                 QRect textRect;
00187                 QRect countRect;
00188                 layoutAccount( option, account, iconRect, textRect, countRect );
00189                 return (iconRect|textRect|countRect).size();
00190         }
00191         
00192         Blokkal::Blog * blog = dynamic_cast<Blokkal::Blog*>( (QObject*) index.data().toULongLong() );
00193         if( blog ) {
00194                 QRect iconRect;
00195                 QRect textRect;
00196                 QRect infoRect;
00197                 layoutBlog( option, index, blog, iconRect, textRect, infoRect );
00198                 return ( iconRect|textRect|infoRect).size();
00199         }
00200         
00201         Blokkal::Io::Category * category = dynamic_cast<Blokkal::Io::Category*>( (QObject*) index.data().toULongLong() );
00202         if( category ) {
00203                 QRect textRect;
00204                 layoutPlainItem( option, index, textRect );
00205                 return textRect.size();
00206         }
00207         
00208 
00209         kWarning() << "encountered invalid data type" << endl;
00210         return QSize( 20,20 );
00211 }
00212 
00213 
00214 unsigned int Blokkal::Ui::BlogDelegate::displayOptions( void ) const
00215 {
00216         return d->displayOptions;
00217 }
00218 
00219 QRect Blokkal::Ui::BlogDelegate::checkBoxRect( const QStyleOptionViewItem & option, const QModelIndex & index ) const
00220 {
00221         if( displayOptions() & DisplayCheckBoxes ) {
00222                 Blokkal::Account * account = dynamic_cast<Blokkal::Account*>( (QObject*) index.data().toULongLong() );
00223                 if( account ) {
00224                         return QRect();
00225                 }
00226         }
00227         else {
00228                 return QRect();
00229         }
00230 
00231         return CheckBoxDelegate::checkBoxRect( option, index );
00232 }
00233 
00234 void Blokkal::Ui::BlogDelegate::layoutAccount( const QStyleOptionViewItem & option,
00235                                                const Blokkal::Account * account,
00236                                                QRect & iconRect,
00237                                                QRect & textRect,
00238                                                QRect & countRect ) const
00239 {
00240         QStyle * const style = QApplication::style();
00241    const int margin = style->pixelMetric( QStyle::PM_FocusFrameHMargin ) + 1;
00242         const int height = option.fontMetrics.height();
00243         const int width = option.rect.width();
00244         const int x = option.rect.x();
00245         const int y = option.rect.y();
00246 
00247         if( displayOptions() & DisplayAccountIcon
00248             || displayOptions() & DisplayAccountStates )
00249         {
00250                 if( option.direction == Qt::LeftToRight ) {
00251                         //x, y, width, height
00252                         iconRect.setRect( x, y, height, height );
00253                 }
00254                 else {
00255                         iconRect.setRect( x + width - height, y, height, height );
00256                 }
00257         }
00258         
00259         textRect.setRect( x, y, width, height );
00260         if( option.direction == Qt::LeftToRight ) {
00261                 if( iconRect.isValid() ) {
00262                         textRect.setLeft( iconRect.right() /*+ margin*/ );
00263                 }
00264                 textRect.setWidth( option.fontMetrics.width( account->id() ) + 2*margin );
00265         }
00266         else {
00267                 if( iconRect.isValid() ) {
00268                         textRect.setRight( iconRect.left() /*- margin*/ );
00269                 }
00270                 textRect.setLeft( textRect.right() - option.fontMetrics.width( account->id() ) - 2*margin );
00271         }
00272 
00273         
00274         if( displayOptions() & DisplayBlogCount ) {
00275                 const int countWidth = QFontMetrics( KGlobalSettings::smallestReadableFont() ).width( d->blogCount( account ) ) + 2*margin;
00276                 if( option.direction == Qt::LeftToRight ) {
00277                         int countX = x + width - countWidth;
00278                         if( textRect.right() + countWidth < x + width ) {
00279                                 countX = textRect.right() /*+ margin*/;
00280                         }
00281                         countRect.setRect( countX,
00282                                            y,
00283                                            countWidth,
00284                                            height );
00285                 }
00286                 else {
00287                         int countX = x;
00288                         if( textRect.left() - countWidth > x ) {
00289                                 countX = textRect.left() /*- margin*/;
00290                         }
00291                         countRect.setRect( countX, y, countWidth, height );
00292                 }
00293         }
00294 
00295         if( option.direction == Qt::LeftToRight ) {
00296                 if( countRect.isValid() ) {
00297                         textRect.setRight( countRect.left() /*- margin*/ );
00298                 }
00299                 else {
00300                         textRect.setRight( x + width );
00301                 }
00302         }
00303         else {
00304                 if( countRect.isValid() ) {
00305                         textRect.setLeft( countRect.right() /*+ margin */);
00306                 }
00307                 else {
00308                         textRect.setLeft( x );
00309                 }
00310         }
00311 }
00312 
00313 void Blokkal::Ui::BlogDelegate::layoutBlog( const QStyleOptionViewItem & option,
00314                                             const QModelIndex & index,
00315                                             const Blokkal::Blog * blog,
00316                                             QRect & iconRect,
00317                                             QRect & textRect,
00318                                             QRect & infoRect ) const
00319 {
00320         Q_UNUSED( blog );
00321         //QStyle * const style = QApplication::style();
00322         //const int margin = style->pixelMetric( QStyle::PM_FocusFrameHMargin ) + 1;
00323         const int height = option.fontMetrics.height();
00324         const int width = option.rect.width();
00325         const int x = option.rect.x();
00326         const int y = option.rect.y();
00327 
00328         QRect checkBoxRect;
00329         
00330         if( displayOptions() & DisplayCheckBoxes ) {
00331                 checkBoxRect = this->checkBoxRect( option, index );
00332         }
00333         
00334         
00335         if( displayOptions() & DisplayBlogIcon ) {
00336                 const int iconHeight = height;//( displayOptions() & DisplayBlogDescription ) ? height + QFontMetrics( KGlobalSettings::smallestReadableFont() ).height(): height;
00337                 if( option.direction == Qt::LeftToRight ) {
00338                         if( checkBoxRect.isValid() ) {
00339                                 iconRect.setRect( checkBoxRect.right(), y, iconHeight, iconHeight );
00340                         }
00341                         else {
00342                                 iconRect.setRect( x, y, iconHeight, iconHeight );
00343                         }
00344                 }
00345                 else {
00346                         if( checkBoxRect.isValid() ) {
00347                                 iconRect.setRect( checkBoxRect.left() - iconHeight, y, iconHeight, iconHeight );
00348                         }
00349                         else {
00350                                 iconRect.setRect( x + width - iconHeight, y, iconHeight, iconHeight );
00351                         }
00352                 }
00353         }       
00354 
00355         textRect.setRect( x, y, width, height );
00356         if( option.direction == Qt::LeftToRight ) {
00357                 if( iconRect.isValid() ) {
00358                         textRect.setLeft( iconRect.right() );
00359                 }
00360                 else if( checkBoxRect.isValid() ) {
00361                         textRect.setLeft( checkBoxRect.right() );
00362                 }
00363                 //textRect.setWidth( option.fontMetrics.width( blog->id() ) + 2*margin );
00364         }
00365         else {
00366                 if( iconRect.isValid() ) {
00367                         textRect.setRight( iconRect.left() );
00368                 }
00369                 else if( checkBoxRect.isValid() ) {
00370                         textRect.setLeft( checkBoxRect.left() );
00371                 }               
00372                 //textRect.setLeft( textRect.right() - option.fontMetrics.width( blog->id() ) - 2*margin );
00373         }
00374 
00375         if( displayOptions() & DisplayBlogDescription ) {
00376                 /*if( iconRect.isValid() ) {
00377                         infoRect.setRect( iconRect.right(),
00378                                           y + height,
00379                                           width,
00380                                           QFontMetrics( KGlobalSettings::smallestReadableFont() ).height() );
00381                 }
00382                 else*/ if( checkBoxRect.isValid() ) {
00383                         infoRect.setRect( checkBoxRect.right(),
00384                                           y + height,
00385                                           width,
00386                                           QFontMetrics( KGlobalSettings::smallestReadableFont() ).height() );
00387                 }
00388                 else {
00389                         infoRect.setRect( x,
00390                                           y + height,
00391                                           width,
00392                                           QFontMetrics( KGlobalSettings::smallestReadableFont() ).height() );
00393                 }
00394         }
00395 }